Check Phone Code
Verify the OTP delivered by POST /v3/phone/send/ and get the final verification result plus phone intelligence: carrier name and line type, virtual (VoIP) and disposable flags, and duplicate usage of the number across your sessions.
How the check finds the verification. Matching is by your application plus the E.164 phone_number — request_id is not an input. The most recent pending verification created within the last 5 minutes is checked. If there is none (never sent, already finalized, or older than 5 minutes) the endpoint returns 200 with status: "Expired or Not Found".
Attempt budget. Each verification allows 3 code attempts. The first two wrong codes return status: "Failed" with the attempts remaining and phone: null; the third wrong code finalizes the verification as Declined with a VERIFICATION_CODE_ATTEMPTS_EXCEEDED warning and returns the full phone report.
Outcomes. Approved — correct code and no declining risk. Declined — terminal: the code was correct but a declining risk matched (a DECLINE action below, a blocklisted or high-risk number), or the attempt budget was exhausted. Failed — wrong code, attempts remaining. Expired or Not Found — nothing to check. On Approved/Declined the request_id equals the send’s request_id (the session id) and phone carries the full report (carrier, is_virtual, is_disposable, warnings, lifecycle, matches); on Failed and Expired or Not Found the request_id is a one-off random UUID.
Risk actions. duplicated_phone_number_action, disposable_number_action, and voip_number_action decide what happens when the corresponding risk is detected on a correct code: DECLINE flips the final status to Declined; NO_ACTION (default) records the risk in phone.warnings without affecting the status.
Billing. Checks are free — delivery is billed on the send side (see Phone Verification Pricing).
Session persistence. A finalized check updates the session created by the send (visible in the Business Console, queryable via GET /v3/session/{sessionId}/decision/) and fires a status.updated webhook.
Sandbox. Sandbox API keys skip all processing: code 123456 returns a static Approved payload with a simplified flat phone object (status, phone_number, country_code, carrier_name, line_type, flags); any other code returns Failed. Nothing is persisted.
Authentication. Send your application’s API key in the x-api-key header. Missing or invalid credentials return 403 ({"detail": "You do not have permission to perform this action."}) — this API never returns 401.
Rate limits. Shared write budget of 300 requests/min per API key, plus the upstream anti-abuse cap of 4 attempts per number per hour; exceeding either returns 429.
Authorizations
Body
The same phone number used in the matching POST /v3/phone/send/ call, in E.164 format. This is what links the check to the send.
20"+14155552671"
The OTP the end user received. Must be 4–8 numeric digits — anything else returns 400 without consuming an attempt. A well-formed but wrong code returns 200 with status: "Failed" and consumes one of the 3 attempts.
4 - 8^[0-9]{4,8}$"123456"
What to do when the same number was already used by a different user (different vendor_data) of your application. DECLINE flips the final status to Declined; NO_ACTION records the risk in phone.warnings and fills phone.matches.
NO_ACTION, DECLINE What to do when the carrier lookup flags the number as a temporary/burner line (phone.is_disposable). DECLINE flips the final status to Declined; NO_ACTION records the risk in phone.warnings.
NO_ACTION, DECLINE What to do when the carrier lookup reports a virtual line type — voip, isp, or vpn (phone.is_virtual). DECLINE flips the final status to Declined; NO_ACTION records the risk in phone.warnings.
NO_ACTION, DECLINE Response
Check completed — wrong codes and missing verifications also return 200; inspect status, not the HTTP code. phone is populated only on finalized outcomes (Approved/Declined), null on Failed, and absent on Expired or Not Found.
On Approved/Declined: the session id of the matched verification — identical to the request_id returned by POST /v3/phone/send/. On Failed and Expired or Not Found: a random one-off UUID that cannot be looked up later.
Approved — correct code, no declining risk. Declined — terminal: a declining risk matched or the attempt budget (3) was exhausted. Failed — wrong code, attempts remaining. Expired or Not Found — no pending verification for this number in the last 5 minutes.
Approved, Declined, Failed, Expired or Not Found Human-readable explanation of the outcome, including the number of attempts remaining after a wrong code.
Full phone report. Present (non-null) only on finalized outcomes (Approved/Declined); null on Failed and absent on Expired or Not Found.
vendor_data of the matched verification's session. null on Expired or Not Found.
metadata of the matched verification's session. null on Expired or Not Found.
Timestamp of this check response.