Seev PlusDocs
Docs
On/Off-Ramp API

KYC Verification

Verify user phone numbers via OTP before they can use the on/off-ramp. Required once per phone number per merchant.

Before a user can create ramp orders, their phone number must be verified via OTP (One-Time Password). This is a lightweight KYC step that ensures the Mobile Money account belongs to the user.

KYC verification is required once per phone number per merchant. After verification, the user can create unlimited orders (subject to limits) without re-verifying.

How it works

  1. Initiate — Your app sends the user's details. An OTP is sent to their phone.
  2. Verify — The user enters the OTP code. You submit it to confirm verification.
  3. Done — The phone is marked as verified. The user can now create ramp orders.

Step 1: Initiate KYC

curl -X POST https://api.your-domain.com/api/v1/ramp/kyc/initiate \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Kofi",
    "last_name": "Mensah",
    "phone": "0241234567",
    "provider_name": "MTN"
  }'

Request body

FieldTypeRequiredDescription
first_namestringYesUser's first name
last_namestringYesUser's last name
phonestringYesUser's phone number (local format, e.g. 0241234567)
provider_namestringYesNetwork provider: MTN, VODAFONE, TELECEL, or AIRTELTIGO

Response

{
  "success": true,
  "data": {
    "kyc_id": "1875fe99-4d75-4883-974e-418cb4e221f7",
    "status": "otp_sent"
  }
}

An SMS with a 6-digit OTP is sent to the user's phone. Store the kyc_id — you need it for verification.

Already verified

If the phone number was already verified for this merchant, the API returns immediately without sending a new OTP:

{
  "success": true,
  "data": {
    "kyc_id": "1875fe99-4d75-4883-974e-418cb4e221f7",
    "status": "already_verified"
  }
}

Step 2: Verify OTP

Collect the OTP code from the user and submit it:

curl -X POST https://api.your-domain.com/api/v1/ramp/kyc/verify \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kyc_id": "1875fe99-4d75-4883-974e-418cb4e221f7",
    "otp_code": "482910"
  }'

Request body

FieldTypeRequiredDescription
kyc_idstringYesThe KYC ID returned from the initiate step
otp_codestringYesThe 6-digit OTP code the user received via SMS

Success response

{
  "success": true,
  "data": {
    "kyc_id": "1875fe99-4d75-4883-974e-418cb4e221f7",
    "phone_verified": true,
    "account_name": "Kofi Mensah"
  }
}

Using the verified phone in orders

After verification, use the same phone number in your ramp order requests. The API will match it against the verified KYC record:

{
  "type": "onramp",
  "fiat_amount": 100,
  "destination_wallet": "GBXYZ...",
  "payment_method": "mobile_money",
  "user": {
    "first_name": "Kofi",
    "last_name": "Mensah",
    "phone": "0241234567",
    "network": "MTN"
  }
}

If the phone hasn't been verified, the order will fail with KYC_REQUIRED.

Error codes

ErrorMeaning
OTP_FAILEDFailed to send OTP — check phone number and network
NOT_FOUNDKYC record not found for the given kyc_id
OTP_INVALIDThe OTP code is incorrect or expired

Best practices

  • Check the initiate response for "status": "already_verified" to skip the OTP step for returning users
  • OTP codes expire after a few minutes — prompt the user to enter it promptly
  • If the OTP fails, call /kyc/initiate again to send a new code
  • Store the verification status in your app so you only call KYC for new users
  • The provider_name must match the user's actual MoMo network for the OTP to be delivered

On this page