Banxa Native supports headless OTP: your app collects the customer's email address, triggers the verification flow server-side, and handles the code entry UI natively. No Banxa-hosted screens, no redirects.
If your app has a login mechanism, the OTP requirement can be disabled entirely — contact your Banxa integration manager. If your app does not have a login mechanism, headless OTP is required before you can process a transaction.
OTP is used to verify a customer's email address as part of identity establishment. It is relevant when:
- Your app does not have its own login or authentication mechanism and you need Banxa to verify the customer's email access
- A customer's identity was created without an email address (sparse identity) and you want to collect and verify email via OTP — if you only need to add an email without verification, use the identity patch endpoint instead
If OTP is not enabled on your account, the endpoints return 403 OtpFeatureNotEnabled.
Both endpoints use HMAC authentication. See Authentication for signing details.
| Action | Endpoint |
|---|---|
| Send OTP code | POST /eapi/v1/verifications/otp |
| Verify OTP code | POST /eapi/v1/verifications/otp/verify |
POST /eapi/v1/verifications/otp
{
"identityReference": "customer-12345",
"email": "[email protected]"
}| Field | Type | Description |
|---|---|---|
identityReference | string | Your stable identifier for this customer |
email | string | The email address to verify |
Success response (200):
{
"message": "OTP sent successfully"
}Banxa sends a short-lived 4-digit code to the provided email address. Your app should prompt the customer to check their inbox and enter the code promptly.
Rate limit: 3 requests per minute per customer.
POST /eapi/v1/verifications/otp/verify
{
"identityReference": "customer-12345",
"email": "[email protected]",
"code": "1234"
}| Field | Type | Description |
|---|---|---|
identityReference | string | Same value used in the send request |
email | string | Same email address used in the send request |
code | string | 4-character code from the email |
Success response (200):
{
"message": "Success"
}On success, the email address is recorded as verified on the customer's identity. You can proceed with eligibility checks and ramp creation.
Rate limit: 4 verification attempts per minute per customer.
OTP can be used to collect and verify a customer's email address after identity creation. An identity created without an email address is valid — the OTP send call writes the email onto the identity record on successful verification.
This pattern is useful when your onboarding flow collects email separately from identity creation:
- Create identity via
POST /eapi/v0/identities/basic— omit theemailfield - When ready to verify the customer's email, call
POST /eapi/v1/verifications/otpwith theidentityReferenceandemail - The email is written onto the identity record on successful verification
If the email address supplied in the OTP flow already exists on a different Banxa identity record, Banxa merges the two records. The identityReference from the newer identity is moved onto the existing account; the newer identity and its associated externalCustomerId are removed.
Practical effect: after a merge, the identityReference you supplied continues to work, but it now refers to the older account. Any KYC state from the older account is carried over.
What to watch for: if a customer uses an email address that belongs to an existing Banxa account (e.g. they previously transacted via a different partner), the merge will silently absorb their new identity into the existing one. The customer's KYC history is preserved, but be aware that the older account's state governs their compliance tier.
A 422 response indicates the code is incorrect:
{
"message": "Code does not match, please try again",
"code": 180,
"traceId": "2f92b534-55a0-4340-9e2a-2575913ff792"
}An incorrect code cannot be corrected — the OTP flow must restart from the beginning. Call POST /eapi/v1/verifications/otp again to issue a new code before prompting the customer to re-enter.
A 429 response is returned when the per-minute limit is reached:
{
"message": "Too many OTP requests. Please try again later.",
"code": 429,
"traceId": "9fafad58-f1eb-44db-a77e-329610b1b755"
}| Limit | Threshold |
|---|---|
| OTP send | 3 per minute per customer |
| OTP verify | 4 per minute per customer |
Present a clear wait-state to the customer rather than retrying silently.
A 403 response means OTP is not enabled on your merchant account. Contact your Banxa integration manager.
A 422 response with "The selected identity reference is invalid." means the identityReference does not exist in Banxa's system. Ensure identity creation has completed successfully before triggering OTP.
If your integration also uses Banxa Hosted Checkout, headless OTP suppresses the email verification screen that Banxa Hosted Checkout would otherwise show to the customer.
| Step | Endpoint | Rate limit |
|---|---|---|
| 1. Send OTP | POST /eapi/v1/verifications/otp | 3/min |
| 2. Verify code | POST /eapi/v1/verifications/otp/verify | 4/min |
On wrong code: restart from step 1. On rate limit: wait and retry. On success: email is verified on the identity record and the customer can proceed.