Skip to content
Markets open
A laptop at a two-factor sign-in step while a phone in hand shows a one-time code
OTP & verification

Codes by text,or by a call

The Verify API sends a one-time code by SMS or reads it aloud on a call, checks what the user types, and bills only the message or call. No per-verification fee.

SMS and voice OTPPumping limits built inNo verification fee

In short

The Verify API makes the code, sends it and checks it: two requests, SMS or voice, with only a hash of the code ever stored.

Codes go out on the best-quality route for each destination, premium-rate and pumping ranges are refused, and every number has a resend cooldown and an hourly cap. You pay the route rate for the SMS or call plus a fee capped at $0.001, with no per-verification charge.

What you can do

  1. 01

    Verify API

    Start and check a code in two requests. Hashed, single use, five attempts.

  2. 02

    Voice OTP

    A call that reads the code aloud, in English, Spanish, French, German, Portuguese or Hindi.

  3. 03

    SMS OTP

    Codes by text in seven languages, sent from your brand name.

  4. 04

    Your own codes

    Keep code generation in your app and send through the SMS or voice API instead.

How it works

Two requests from sign-up form to verified number

The Verify API makes the code, sends it and checks it. You never store a code, and you pay only for the message or call that carried it.

  1. Take a key

    Open a free account and create a key with the Verify permission. A test key runs the whole flow on sandbox credit and hands you the code, so you can finish a check without a phone.

  2. Start a verification

    POST /verify/start with the number and a channel: sms, or voice for a call that reads the digits aloud. Codes go out on the best-quality route for the destination unless you name a strategy.

  3. Check what they typed

    POST /verify/check with the verification ID and the code. The answer is approved, denied, expired or max_attempts, and a code works once.

  4. Set the guard rails

    Fund a prepaid balance, set a daily spend alert and a low-balance alert. Per-number limits and blocked premium-rate ranges are on from the first request.

Verify API

No codes to generate, store or expire

Start a verification and we create a code of 4 to 10 digits, send it in your brand name and keep only a hash of it. Check it with the ID we returned: five attempts, one use, ten minutes by default. The code never appears in a database row, a log line or a live API reply, so there is nothing of value to leak on your side or ours.

  • SMS in English, Spanish, French, German, Portuguese, Hindi or Arabic; voice in all but Arabic
  • Expiry from 1 to 60 minutes, code length from 4 to 10 digits
  • Prefer your own codes? Send them through the SMS API, or speak them with POST /comms/voice-otp
Verify API · start and checkExample
1. Send the code
SMS or voice
POST /v1/verify/start

{ "to": "+447700900431",
  "channel": "voice",
  "language": "es",
  "brand": "Acme" }
{ "verificationId": "5f0c…e21a",
  "status": "pending",
  "expiresAt": "…T10:10:00Z",
  "maxAttempts": 5 }

We generate the code and keep only a hash of it. The call reads the digits aloud in Spanish, twice, then hangs up.

2. Check what the user typed
5 attempts, single use
POST /v1/verify/check

{ "verificationId": "5f0c…e21a",
  "code": "482916" }
approveddeniedexpiredmax_attempts

Voice OTP

A code they can hear, for when a text will not do

Landlines, patchy SMS coverage and users who never see the text: start the same verification with channel voice and the phone rings with the code. The call names your brand, reads the digits one at a time, repeats them, and hangs up. It rides the voice route for the destination and is billed on that route's increment, with no text-to-speech surcharge.

  • Six spoken languages: English, Spanish, French, German, Portuguese and Hindi
  • The digits are read twice by default, up to three times
  • If a carrier refuses the SMS, the reply tells you to retry by voice, and the refused attempt does not count against the number's limit
A woman at a desk listening to a phone call, pen ready over a notepad, to take down a spoken sign-in code

SMS pumping

An attack meets limits before it meets your balance

SMS pumping turns a sign-up form into someone else's revenue: scripts request codes to numbers that earn a payout per message. The Verify API refuses premium-rate, satellite and known pumping ranges outright, caps how often one number or one number range can be sent a code, and fails closed if those limits cannot be checked. Behind that sits a prepaid balance with a floor at zero, so the worst day has a ceiling you set.

  • 5 codes per number per hour, 30 seconds between resends, 20 per number range per hour
  • A daily cap of 1,000 verifications per account, raised on request
  • Embargoed destinations and numbers on your do-not-contact list are refused before anything is charged
  • Daily spend and low-balance alerts, the balance.low webhook, and auto-recharge with its own daily cap
Billing · Spending alertsExample
Balance
$214.60
Prepaid, floor at $0.00
Spent today
$41.06
Since 00:00 UTC
Spending alerts
Email alerts on
Daily spend cap alert$40.00

Alert me when today's spend exceeds $40.00.

Low-balance alert

Alert me when my balance drops below $50.00.

$50.00
Auto-recharge on
Saved card
When balance falls below
$50.00
Reload amount
$100.00
Daily cap
$300.00
Daily spend cap reached14:05 UTC · also by email

You've spent $41.06 today, above your $40.00 daily cap.

One request

Verify a number in two requests

No onboarding call and no waiting for an account manager. Create an account, take your API key and post to the endpoint below, the same one that carries live traffic. Test keys let you try it without sending a real message or call.

verify.shone request
curl https://packetexchange.io/api/v1/verify/start \
  -H "Authorization: Bearer $PE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"+447700900123","channel":"voice"}'

curl https://packetexchange.io/api/v1/verify/check \
  -H "Authorization: Bearer $PE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"verificationId":"<id>","code":"482916"}'
REST API + MCPrated per SMS or call · ledger-verified

Built for verification

What sits between your login and the handset

Quality-first routing

Codes default to the best-quality strategy: the most specific prefix, then the highest stated answer rate, with price only breaking a tie.

SMS or voice, one API

The same start and check requests for both channels. Switch a user to a call without changing how you check the code.

Hashed, single-use codes

Only a keyed hash is stored. Five wrong guesses or the expiry ends the verification, and an approved code cannot be used twice.

Risky ranges refused

Premium-rate, satellite and known pumping ranges are refused before a limit is spent or a cent is charged, and so are embargoed destinations.

Limits per number and range

Resend cooldown, hourly caps per number and per number range, and a daily account cap. Two simultaneous resend taps cannot both slip through.

Keys scoped to verify

Give your auth service a key that can start and check verifications and nothing else. It cannot buy routes, top up or read your account.

Seven languages

Message templates in seven languages and spoken codes in six, with your brand name in the text or read out at the start of the call.

A record of every attempt

Look up any verification for its status, attempts and the cost of its message or call, and find the send itself in your message history and CDRs.

Why PacketExchange

Verification without the verification tax

A one-time code is a short message or a short call. Here it is priced like one.

No per-verification fee

A code costs the route's rate for the SMS or call, plus a platform fee capped at $0.001. Nothing is added per attempt, per successful check or per month.

Built to land, not just to leave

Quality-first routing and stated route tiers put codes on the paths most likely to reach the handset, because a code that never arrives is a sign-up that never finishes.

Exposure capped in advance

Blocked ranges, per-number limits, a prepaid balance with a floor at zero and a daily cap on auto-recharge put a number on your worst day before it happens.

Hosted or yours, same price

Use the Verify API, or keep code generation in your own app and send through the SMS or voice API. Both bill the same way, so there is nothing to migrate away from.

Side by side

A typical verify product, and this one

What you pay
A typical verify product: A price per verification, on top of the messages it sends
On PacketExchangeThe route's rate for the SMS or call, plus a fee capped at $0.001
Channels
A typical verify product: Voice sold as a separate add-on
On PacketExchangeSMS and voice through the same start and check requests
Route choice
A typical verify product: Decided inside the provider, out of view
On PacketExchangeBest quality by default, or cheapest, balanced or a route you bought
Spend exposure
A typical verify product: Often postpaid, so a pumping attack surfaces on the invoice
On PacketExchangeBlocked risky ranges, per-number limits and a prepaid balance with a floor at zero
Retries
A typical verify product: A double tap can send two codes
On PacketExchangeA 30-second resend cooldown per number, claimed atomically

Built for

Who runs traffic on it

  • Login 2FA

    A second factor at sign-in and for step-up checks.

  • Transaction signing

    Confirm payments and account changes.

  • Sign-up checks

    Prove the number is real before the account is.

Pricing

A code costs what its message or call costs

verification fee on top
$0
platform fee on the carrier cost
2%
fee cap per code
$0.001

An SMS code is billed per segment at the route's rate. A voice code is billed at the route's per-minute rate on its billing increment. Either way the platform fee is 2% of that amount, never above $0.001, and there is no verification fee or speech surcharge on top.

No monthly fee and no minimum volume. Fund a prepaid balance from $5 by card or crypto, or from $100 by bank wire.

See developer pricing

What you pay for

  • Route rate

    Per SMS segment or per call, as listed on the route for the destination's longest matching prefix.

  • Platform fee

    2% of the carrier cost, capped at $0.001 per code.

  • Refused sends

    An SMS a carrier refuses is reversed in full and does not count against the number's hourly limit.

  • Rates in the open

    Every SMS and voice route shows its rate before you send, on the marketplace and on developer pricing.

Test keys run the whole flow on invite-only sandbox credit, return the code so you can check it, and deliver nothing.

Questions

What security and growth teams ask

The questions buyers ask before they start. Anything not covered here is in the help centre, or ask the team directly.

Do I have to use the Verify API?

No. The Verify API generates, sends and checks the code for you. If you would rather keep codes in your own app, send them through POST /comms/sms in your own wording, or have a call speak them with POST /comms/voice-otp. The price is the same either way: the message or call.

Does it fall back from SMS to voice automatically?

No, you decide. If a carrier refuses the SMS, the start request returns an error that suggests channel voice, and the refused attempt does not use up the number's hourly limit. Start again with channel voice and the same check request works.

What does one code cost?

For SMS, the route's per-segment rate for the destination plus 2%, capped at $0.001. A short code message fits in one segment. For voice, the route's per-minute rate for the billed seconds of a short call, plus the same capped fee. The cost of each send is recorded against the verification.

How do I limit what an SMS pumping attack can cost?

The Verify API already refuses premium-rate and known pumping ranges and caps codes per number and per number range. Add a prepaid balance sized to a few normal days, a daily spend alert, a capped auto-recharge, and bot checks in your sign-up form where you can see the requests.

Which sender or caller ID is used?

SMS codes go from your brand name as an alphanumeric sender unless you pass your own. Every SMS route lists whether it carries alphanumeric, numeric or pre-registered senders before you buy. A voice code presents the caller ID you pass in from.

Can I test the whole flow first?

Yes. A test key runs against invite-only sandbox credit. The start is routed and priced on a real route, nothing is delivered, and the reply includes the code as testCode so you can complete the check in your test suite.

Get started

Put your next sign-in code on a quality route

Open a free account, build the flow on a test key, then fund a balance from $5 and go live with SMS and voice codes on the same two requests.