Skip to main content
Use POST /v3/verify to check the code your user entered against an existing OTP transaction. Submit the otp_id from the original POST /v3/request or POST /v3/send response alongside the code the user provided. OTP.ID records the attempt and returns whether the code matched. A wrong code is not an HTTP error — read data.verified in the response body to determine the outcome.

Endpoint

Request Headers

Request Body

string
required
The transaction ID returned by POST /v3/request or POST /v3/send. Format: OTP + YYYYMMDD + 4 letters + 6 digits (e.g. "OTP20260807ABCD000001").
string
required
The code submitted by the user. Pass it exactly as entered — OTP.ID compares it against the transaction’s stored code.

Response Fields

string
The transaction ID, echoed from your request.
boolean
  • true — the code matched; the transaction is now permanently marked as used
  • false — the code did not match; the attempt has been recorded against the transaction’s attempt counter
string
Human-readable reason string.
  • "" (empty string) — verification was successful
  • "mismatch" — the code the user entered did not match

Example

Response Scenarios

A code mismatch returns HTTP 200, not HTTP 4xx. Always check data.verified in your code — do not use the HTTP status code to detect a wrong code. A verified: false response still counts as an attempt.

Success — correct code

Mismatch — wrong code (HTTP 200)

Expired — OTP past its TTL (HTTP 422)

Too many attempts (HTTP 422)

Already used (HTTP 422)

Error Codes

All errors follow the shape {"success": false, "data": null, "error": {"code": "...", "message": "..."}}.

Webhooks

A successful verification (where verified returns true) also triggers the otp.verified webhook asynchronously. Your server receives the event after OTP.ID records the verification — implement the webhook to react to verifications server-to-server without polling.
After a transaction reaches TOO_MANY_ATTEMPTS, subsequent verify calls for that otp_id will continue to return TOO_MANY_ATTEMPTS — the lock is permanent. You must start a new OTP transaction.