Passwire API
Send and verify one-time codes over SMS and voice with two endpoints. Most teams are live in under an hour.
Quickstart
The full flow is two calls: start a verification (Passwire sends the code), then check the code the user entered.
# 1 — start a verification curl https://api.passwire.dev/v1/verify/start \ -H "Authorization: Bearer $PASSWIRE_KEY" \ -d '{ "to": "+14165550142", "channel": "sms" }' # → { "verification_id": "vr_8Kd2...", "status": "pending", "channel": "sms" } # 2 — check the code your user typed in curl https://api.passwire.dev/v1/verify/check \ -H "Authorization: Bearer $PASSWIRE_KEY" \ -d '{ "verification_id": "vr_8Kd2...", "code": "418207" }' # → { "status": "approved" }
Authentication
Every request to a /v1 endpoint requires your secret API key as a bearer token. Keep it server-side — never ship it in client code.
Authorization: Bearer pw_live_xxxxxxxxxxxxxxxx
Base URL
https://api.passwire.dev
All requests are JSON over HTTPS. Send Content-Type: application/json on POST requests.
Start a verification
POST/v1/verify/start
Generates a one-time code and delivers it to the recipient over the chosen channel. Returns a verification_id you'll use to check the code.
| Field | Type | Description |
|---|---|---|
| to required | string | Recipient phone number in E.164 format, e.g. +14165550142. |
| channel optional | string | "sms" (default) or "voice". Voice reads the code aloud. |
{
"verification_id": "vr_8Kd2a1f0c93b7e6d5a4c",
"status": "pending",
"channel": "sms"
}
Check a code
POST/v1/verify/check
Validates the code the user entered against the verification. Codes are single-use and expire after 10 minutes.
| Field | Type | Description |
|---|---|---|
| verification_id required | string | The id returned by /verify/start. |
| code required | string | The code the end user entered. |
{ "status": "approved" }
// on a wrong code:
{ "status": "denied", "attempts_remaining": 4 }
Health check
GET/v1/health — returns { "ok": true }. No auth required. Use it for uptime monitoring.
Verification statuses
| Status | Meaning |
|---|---|
pending | Code generated and sent; awaiting check. |
approved | Correct code submitted. The verification is consumed. |
denied | Wrong code. See attempts_remaining. |
expired | Code expired, never existed, or attempts exhausted. |
Errors
Errors return a non-2xx status and a JSON body with an error field.
| HTTP | error | Cause |
|---|---|---|
| 401 | missing_api_key / invalid_api_key | Bad or absent bearer token. |
| 400 | invalid_json | Body wasn't valid JSON. |
| 422 | invalid_to | Number isn't valid E.164. |
| 422 | invalid_channel | Channel wasn't sms or voice. |
| 422 | missing_fields | Required field absent on check. |
| 500 | internal_error | Something broke on our side. |
Limits & behavior
Need higher volume, dedicated numbers, or email verification? Talk to us. · © 2026 Passwire