Skip to main content
The Onramp Verification APIs let Coinbase manage OTP verification of a user’s phone number and email on your behalf. Instead of running your own OTP infrastructure, you call these APIs to verify both contact channels and pass the resulting verification IDs to the Create Onramp Order API.
Onramp Verification is available for Guest Checkout (Headless Onramp) integrations. Both phone number and email must be verified before creating an order. This API is an alternative to self-managed OTP verification — you do not need both approaches.
Access to these APIs requires allowlisting. During Headless Onramp onboarding, contact the Onramp team to enable Onramp-managed verification for your application. You can build and test the full flow in sandbox without allowlisting.

How it works

1

Initiate verification

Call POST /v2/onramp/verifications with the channel and the user’s phone number or email. Coinbase sends a 6-digit code and returns a verificationId. The code is valid for 10 minutes.
2

Submit the OTP code

Collect the code from the user and call POST /v2/onramp/verifications/{verificationId}/submit. On success the verification is marked verified and is valid for 60 days.
3

Create the order

Pass the returned verification IDs — smsVerificationId for phone, emailVerificationId for email — to the Create Onramp Order API. Onramp validates the server-side verification records for both channels.

Integration flow

1. Initiate verification

cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/verifications' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{
    "channel": "sms",
    "destination": "+12055555555"
  }'
channel is sms or email. destination is the phone number (E.164) or email address to send the code to. Response:
{
  "verificationId": "onramp_verification_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "otpExpiresAt": "2025-04-24T00:10:00Z"
}
Persist the verificationId and prompt the user to enter the code before otpExpiresAt.

2. Submit the OTP code

cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/verifications/onramp_verification_a1b2c3d4-e5f6-7890-abcd-ef1234567890/submit' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{
    "otpCode": "123456"
  }'
The destination does not need to be re-sent — Onramp uses the value captured at initiation. Response:
{
  "verificationId": "onramp_verification_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "verificationExpiresAt": "2025-06-23T00:00:00Z"
}
The verificationId is valid for 60 days and must be re-verified afterward.

3. Create the order

After verifying both channels, pass the verification IDs when creating an order. Use smsVerificationId for the phone verification and emailVerificationId for the email verification.
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/orders' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{
    "smsVerificationId": "onramp_verification_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "emailVerificationId": "onramp_verification_b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "...": "remaining order fields"
  }'

Sandbox testing

You can exercise the full verification flow in sandbox without being on the allowlist, so you can integrate before production access is granted. Sandbox requests never send a real SMS or email and never touch a real user record.

Sandbox values

InputSandbox value
SMS destinationAny number prefixed with +1000 (e.g. +10005550100)
Email destinationAny address ending in @sandbox.test (e.g. tester@sandbox.test)
otpCode (on submit)000000

Sandbox walkthrough

1. Initiate with a sandbox phone number:
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/verifications' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{
    "channel": "sms",
    "destination": "+10005550100"
  }'
The response returns a sandbox verificationId (recognizable by the onramp_verification_00000000- prefix):
{
  "verificationId": "onramp_verification_00000000-a1b2-c3d4-e5f6-7890abcdef12",
  "otpExpiresAt": "2025-04-24T00:10:00Z"
}
2. Submit the sandbox OTP code (000000):
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/verifications/onramp_verification_00000000-a1b2-c3d4-e5f6-7890abcdef12/submit' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{
    "otpCode": "000000"
  }'
{
  "verificationId": "onramp_verification_00000000-a1b2-c3d4-e5f6-7890abcdef12",
  "verificationExpiresAt": "2025-06-23T00:00:00Z"
}
3. Test the error path — submitting any code other than 000000 returns an error:
cdpcurl -X POST '.../submit' \
  -k ~/Downloads/cdp_api_key.json \
  -d '{ "otpCode": "999999" }'
{
  "errorType": "otp_verification_code_invalid",
  "errorMessage": "OTP verification failed"
}

Error reference

HTTPCauseResolution
400Invalid channel, destination, or OTP codeCheck errorMessage and the request fields.
401Missing or invalid API key, or app not allowlistedVerify your API key. Contact the Onramp team to be allowlisted.
404Verification ID not found (submit)Ensure you are using the verificationId returned by initiate.
429Rate limit exceededBack off and retry with exponential backoff.

POST /v2/onramp/verifications

Full API reference for initiating a verification.

POST /v2/onramp/verifications/\{verificationId\}/submit

Full API reference for submitting an OTP code.