Compliance & KYC
Every safeguard the BCC and FATF require is enforced at the API boundary. Skipping a field is not an option — the request is rejected with a clear error code, not silently degraded.
FATF R.16 (Recommendation 16 — wire transfers)
FATF R.16 requires accurate and meaningful originator + beneficiary information on every cross-border transfer.
Fields Moko enforces from FATF R.16
| Field | Where |
|---|---|
sender_first_name, sender_last_name | /inbound required |
sender_nationality | /inbound required |
sender_birthdate | /inbound required |
identity_number | /inbound required |
sender_document_type (enum) | /inbound required — one of PASSPORT, NATIONAL_ID, DRIVING_LICENCE, VOTER_CARD, OTHER |
receiver_first_name, receiver_last_name | /inbound required |
receiver_nationality | /inbound required |
receiver_birthdate | /inbound required |
reason_of_transaction (enum) | /inbound required — see enum below |
source_of_funds (enum) | /inbound required — see enum below |
expected_receiver_name | /inbound required — fuzzy-matched against the telco subscriber record |
reason_of_transaction enum (23 values)
FAMILY_SUPPORT, EDUCATION, MEDICAL, BUSINESS_PAYMENT, SALARY, GIFT, SAVINGS, PROPERTY_PURCHASE, TRAVEL, LOAN_REPAYMENT, INVESTMENT, CONSTRUCTION, RENT, GENERAL, FUEL, REPAIRS, PERSONAL_CARE, FOOD_AND_GROCERIES, TRANSPORT, SHOPPING, ENTERTAINMENT, DONATIONS, OTHER.
Invalid value → RMT-1016.
source_of_funds enum
SALARY, BUSINESS_INCOME, SAVINGS, INVESTMENT, PENSION, GIFT, LOAN, SALE_OF_ASSET, INHERITANCE, OTHER.
Invalid value → RMT-1017.
Name-match on /inbound
Moko does a fuzzy match between the merchant's declared expected_receiver_name and the actual telco subscriber name.
- Case-insensitive
- Token-set based (order and casing ignored, but tokens must overlap)
- Rejects abbreviated or truncated names (a 2-char first name like
AbforAbdullahis rejected at the sanction-defense layer withRMT-1010before the name-match even runs)
If your declared name does not match the telco record, you receive RMT-4006 with the telco name and a match score. Fix the expected_receiver_name and re-submit — the reference is idempotent so a retry does not duplicate the transaction.
BCC RTS Art.66 Instr.15
DRC's central bank regulation on cross-border remittance record-keeping. Requires extended KYC and address information on both legs.
Fields Moko enforces from BCC RTS Art.66
| Field | Where |
|---|---|
sender_birthplace | /inbound required |
receiver_current_address or receiver_permanent_address | /inbound required — at least one. RMT-1018 if both missing. |
receiver_document_type | /inbound required |
receiver_document_number | /inbound required |
ScreenShield (sanctions screening)
Every sender and every receiver is screened against the Vodacom AML feed in real time.
- Match found on the receiver → transaction rejected up-front
- Match found on the sender → transaction accepted but placed on
Holdstatus; Moko compliance reviews and surfaces the outcome in the partner portal - No match → transaction proceeds
Data protection
- PII columns are Fernet-encrypted at rest
- Pickup codes are hashed
- Merchant secrets are stored as scrypt hashes
- Callbacks are HMAC-SHA256 signed and delivered only over TLS 1.2+
What NOT to do
- Do not fake
sender_birthplace,receiver_document_number, or any other KYC field to pass the schema check. Moko audits inbound payloads; systematic fake data on a merchant account is a Go Live-blocking issue. - Do not re-use the same
referencefor two different transactions. The API is idempotent onreference, so we return the first result. - Do not forward the raw sender document image to Moko — we do not accept it. All KYC is field-based.
