Skip to main content

Overview

KYC is the authoritative store for customer identity.

Get a token

POST /api/generate-token
Content-Type: application/json

{ "keyId": "00000000-0000-4000-8000-000000000000", "secret": "<your-api-secret>" }
Use it in requests:
Authorization: Bearer <token>

Customers

Upsert customer

POST /api/v1/kyc/customers
Authorization: Bearer <token>
Content-Type: application/json

{
  "legalName": "Jane Doe",
  "type": "PERSON",
  "mobile": "+255700000000",
  "email": "[email protected]",
  "dob": "1995-01-10",
  "nationalId": "NID12345",
  "address": { "line1": "Street 1", "city": "Dar" }
}
Response
{
  "customerId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "legalName": "Jane Doe",
  "type": "PERSON"
}

Possible payloads

PERSON
{
  "legalName": "Jane Doe",
  "type": "PERSON",
  "mobile": "+255700000000",
  "email": "[email protected]",
  "dob": "1995-01-10",
  "nationalId": "NID12345",
  "address": { "line1": "Street 1", "city": "Dar", "country": "TZ" }
}
BUSINESS
{
  "legalName": "ACME LTD",
  "type": "BUSINESS",
  "mobile": "+255711111111",
  "email": "[email protected]",
  "address": { "line1": "Plot 10", "city": "Dar", "country": "TZ" }
}

Field rules

  • type: PERSON or BUSINESS
  • dob: yyyy-MM-dd when provided
  • email, mobile, nationalId, address: optional

Get customer

GET /api/v1/kyc/customers/{customerId}
Authorization: Bearer <token>

KYC

Submit KYC

POST /api/v1/kyc/customers/{customerId}/kyc
Authorization: Bearer <token>
Content-Type: application/json

{
  "documents": [
    { "type": "id_front", "url": "https://files.example.com/123/front.jpg" },
    { "type": "id_back", "url": "https://files.example.com/123/back.jpg" }
  ],
  "identifiers": [
    { "type": "nid", "value": "NID12345" }
  ],
  "metadata": { "issuedBy": "NIDA" }
}
Response
{ "status": "received" }

Field rules

  • documents: required array of { type, url }
  • identifiers: optional array of { type, value } (e.g., nid, passport)
  • metadata: optional object for provider-specific notes

Add identifiers

POST /api/v1/kyc/customers/{customerId}/identifiers
Authorization: Bearer <token>
Content-Type: application/json

[
  { "type": "passport", "value": "AB1234567" }
]

Add documents

POST /api/v1/kyc/customers/{customerId}/documents
Authorization: Bearer <token>
Content-Type: application/json

[
  { "type": "address_proof", "url": "https://files.example.com/poa.pdf" }
]

Lifecycle

Activate customer

POST /api/v1/kyc/customers/{customerId}/activate
Authorization: Bearer <token>
Content-Type: application/json

{ "activatedOn": "2025-01-01" }

Deactivate customer

POST /api/v1/kyc/customers/{customerId}/deactivate
Authorization: Bearer <token>
Content-Type: application/json

{ "deactivatedOn": "2025-02-01" }

Field rules

  • activatedOn / deactivatedOn: yyyy-MM-dd
GET /api/v1/kyc/customers/search?query=jane
Authorization: Bearer <token>

Verification

Verify identity

POST /api/v1/kyc/identity/verify
Authorization: Bearer <token>
Content-Type: application/json

{
  "identityType": "DRIVING_LICENCE",
  "identityNumber": "T1234567",
  "countryCode": "TZ",
  "issueDate": "2020-01-01",
  "isConsent": "true"
}
Response
{
  "matched": true,
  "fullName": "Jane A Doe",
  "dob": "1995-01-10",
  "nationality": "TZ"
}

Field rules

  • identityType: one of DRIVING_LICENCE, TIN, VOTERS_CARD, ZANID
  • countryCode: must be TZ
  • issueDate: yyyy-MM-dd; required for TIN and DRIVING_LICENCE
  • isConsent: must be string "true"

Verify mobile

POST /api/v1/kyc/mobile/verify
Authorization: Bearer <token>
Content-Type: application/json

{
  "phoneNumber": "+255700000000",
  "firstName": "Jane",
  "lastName": "Doe"
}
Response
{ "matched": true, "operator": "Vodacom" }

Field rules

  • phoneNumber: include country code (e.g., +255700000000)
  • firstName, lastName: required; middleName optional

Verify business

POST /api/v1/kyc/business/verify
Authorization: Bearer <token>
Content-Type: application/json

{
  "registrationNumber": "12345",
  "countryCode": "TZ",
  "isConsent": "true"
}

Field rules

  • countryCode: must be TZ
  • isConsent: must be string "true"
Response
{
  "matched": true,
  "legalName": "ACME LTD",
  "status": "ACTIVE"
}