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.

curl
# 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.

header
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.

FieldTypeDescription
to requiredstringRecipient phone number in E.164 format, e.g. +14165550142.
channel optionalstring"sms" (default) or "voice". Voice reads the code aloud.
200 — response
{
  "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.

FieldTypeDescription
verification_id requiredstringThe id returned by /verify/start.
code requiredstringThe code the end user entered.
200 — response
{ "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

StatusMeaning
pendingCode generated and sent; awaiting check.
approvedCorrect code submitted. The verification is consumed.
deniedWrong code. See attempts_remaining.
expiredCode expired, never existed, or attempts exhausted.

Errors

Errors return a non-2xx status and a JSON body with an error field.

HTTPerrorCause
401missing_api_key / invalid_api_keyBad or absent bearer token.
400invalid_jsonBody wasn't valid JSON.
422invalid_toNumber isn't valid E.164.
422invalid_channelChannel wasn't sms or voice.
422missing_fieldsRequired field absent on check.
500internal_errorSomething broke on our side.

Limits & behavior

Codes are 6 digits, valid for 10 minutes, and single-use. A verification allows 5 attempts before it's burned. Codes are stored hashed — Passwire never retains the plaintext.

Need higher volume, dedicated numbers, or email verification? Talk to us. · © 2026 Passwire