Verify
Verify (one-time codes)
Confirm that someone owns a phone number: they receive a one-time code by SMS, and you check the code they enter.
Phone Number Verification (OTP)
Use the Verify API to confirm ownership of a phone number before sending commercial messages. Your end-user receives a one-time code via SMS; submit it to the check endpoint to confirm.
A verification costs the SMS price per segment plus a verification upcharge; one the carrier refuses is refunded. Codes are 6 digits by default (codeLength 4, 6 or 8; REST code_length) and valid for 10 minutes (ttlMinutes, 1 to 60; REST ttl_minutes). Five wrong codes end it with VERIFICATION_MAX_ATTEMPTS, and an expired one answers VERIFICATION_EXPIRED. With a test key nothing is sent and the code is all zeros.
// Start a verification (sends OTP SMS)
const { data: verification, error } = await honkio.verify.start({
from: '+1416XXXXXXX',
to: '+1613XXXXXXX',
codeLength: 6,
ttlMinutes: 10,
appName: 'Acme',
})
if (error) throw new Error(error.message)
// { id: 'clxxx...', status: 'pending', code_length: 6, ... }
console.log(verification.id, verification.status)# Start a verification (sends OTP SMS)
curl -X POST https://api.honkio.ca/v1/verify \
-H "Authorization: Bearer mk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+1416XXXXXXX",
"to": "+1613XXXXXXX",
"code_length": 6,
"ttl_minutes": 10,
"app_name": "Acme"
}'
# Response: { "id": "clxxx...", "status": "pending", "code_length": 6, ... }// Check the code submitted by your user
const { data, error } = await honkio.verify.check('clxxx...', { code: '483721' })
if (error?.name === 'VERIFICATION_INVALID_CODE') {
console.log(error.details) // { attempts_remaining: 4 }
} else if (error) {
throw new Error(error.message)
} else {
console.log(data.status) // 'verified'
}# Check the code submitted by your user
curl -X POST https://api.honkio.ca/v1/verify/clxxx.../check \
-H "Authorization: Bearer mk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "code": "483721" }'
# Response 200: { "status": "verified", ... }
# Response 422: { "code": "VERIFICATION_INVALID_CODE", "attempts_remaining": 4 }// Fetch status at any time
const { data, error } = await honkio.verify.get('clxxx...')
if (error) throw new Error(error.message)
console.log(data.status, data.attempts_remaining)# Fetch status at any time
curl https://api.honkio.ca/v1/verify/clxxx... \
-H "Authorization: Bearer mk_live_YOUR_KEY"In test mode the code is always all zeros for the chosen length (e.g. 000000 for 6-digit). No SMS is sent and nothing is billed, and the from number can be any valid Canadian or US number, so you can try it before you buy a number (a toll-free one must still be yours and verified). Every verification returns a "mode" field of "LIVE" or "TEST" so you can tell a simulated verification from a real one.
Live codes are watched for SMS pumping: bots requesting codes nobody enters, at your expense. If fewer than 1 in 5 of the codes sent over an hour are entered (once 25 or more went out), new codes pause for 6 hours. If most of an hour's codes go to one number range (+1 NPA NXX, at least 10 numbers), codes to that range pause for 24 hours. A paused start answers 403 SENDING_PAUSED with channel "verify" in its details, costs nothing, and the account owner is notified. Your other messages keep going. Put a CAPTCHA or a rate limit in front of the form that requests codes. The account owner can resume codes early from the Verify page of the dashboard or with DELETE /v1/verify/pause, and GET /v1/send-limit shows the pause in verify_pause.
HonkIO