API reference
Verify
Phone number verification (SMS OTP) with per-verification upcharge.
/v1/verifyList verifications
verify:rNode.js SDKhonkio.verify.list()Returns a paginated list of verifications for the authenticated account, newest first.
Requires verify:r.
Parameters
| Parameter | Type | Description |
|---|---|---|
limitquery | integer |
|
offsetquery | integer |
|
statusquery | string | Filter by status
|
Responses
200A page of verifications, newest first.
Field Type Description totalrequiredinteger Total matching records.
limitrequiredinteger offsetrequiredinteger data[]requiredobject[] idrequiredstring phone_numberrequiredstring from_numberrequiredstring statusrequiredstring - One of: pending | verified | expired | max_attempts
attemptsrequiredinteger code_lengthrequiredinteger app_namerequiredstring - Can be null
moderequiredstring TEST verifications are simulated: no SMS is sent, nothing is billed, and the code is always 000000 padded to code_length.
- One of: LIVE | TEST
cost_centsrequiredinteger Cost in cents CAD. On a TEST verification this is 0: nothing was charged.
expires_atrequiredstring - Format: date-time
verified_atrequiredstring - Format: date-time
- Can be null
created_atrequiredstring - Format: date-time
- 401Missing, invalid, revoked or expired API key.The standard error body.
- 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
- 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
- 422VALIDATION_ERROR: the request failed validation; details names the fields.The standard error body.
- 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
- 500Unexpected server error.The standard error body.
Example
const { data, error } = await honkio.verify.list({ status: 'pending', limit: 20 })
if (error) throw new Error(error.message)
console.log(data.total)curl https://api.honkio.ca/v1/verify \
-H "Authorization: Bearer mk_live_YOUR_KEY"/v1/verifyStart a phone number verification
verify:wNode.js SDKhonkio.verify.start()Sends an OTP to the specified Canadian phone number.
Billed at your standard per-part message rate (the OTP is one part unless app_name is long or uses non-GSM characters; the charge is settled to the carrier's part count) plus a per-verification upcharge: see verification_upcharge_cents from GET /v1/pricing. A verification the carrier rejects is refunded in full.
Options:
code_length: digits in the OTP,4,6(default), or8ttl_minutes: how long the code is valid (1 to 60 min, default 10)app_name: brand name shown in the SMS, e.g."Acme"→ "Your Acme verification code is: …"
In test mode (mk_test_... key) no SMS is sent; the code is always all zeros for the chosen length (e.g. 000000 for 6-digit, 0000 for 4-digit).
Requires verify:w.
Request body
| Field | Type | Description |
|---|---|---|
fromrequired | string | Your HonkIO number (E.164, must be active on your account) |
torequired | string | The phone number to verify (E.164, Canadian numbers only) |
code_length | integer | OTP digit length (default: 6)
|
ttl_minutes | integer | Minutes until the code expires (default: 10)
|
app_name | string | Brand name shown in the SMS body (default: HonkIO)
|
Responses
201Verification started: the code was sent (LIVE) or simulated (TEST, code all zeros).
Field Type Description idrequiredstring phone_numberrequiredstring from_numberrequiredstring statusrequiredstring - One of: pending | verified | expired | max_attempts
attemptsrequiredinteger code_lengthrequiredinteger app_namerequiredstring - Can be null
moderequiredstring TEST verifications are simulated: no SMS is sent, nothing is billed, and the code is always 000000 padded to code_length.
- One of: LIVE | TEST
cost_centsrequiredinteger Cost in cents CAD. On a TEST verification this is 0: nothing was charged.
expires_atrequiredstring - Format: date-time
verified_atrequiredstring - Format: date-time
- Can be null
created_atrequiredstring - Format: date-time
- 401Missing, invalid, revoked or expired API key.The standard error body.
- 402INSUFFICIENT_BALANCE: the balance cannot cover the send. Also PAYMENT_REQUIRED when a LIVE key is used before the first top-up.The standard error body.
- 403ACCOUNT_NOT_VERIFIED, PHONE_NUMBER_NOT_OWNED, ALLOW_LIST_BLOCKED, DENY_LIST_BLOCKED or SENDING_PAUSED.The standard error body.
- 422VALIDATION_ERROR, NON_CANADIAN_NUMBER, RESERVED_DESTINATION, UNDELIVERABLE_NUMBER, NOT_A_MOBILE_NUMBER or LINK_SHORTENER_BLOCKED. A refused start costs nothing.The standard error body.
- 429RATE_LIMITED (one start per recipient per 60 seconds, Retry-After 60), DAILY_LIMIT_REACHED, FANOUT_LIMIT_REACHED, NUMBER_RATE_LIMITED or RECIPIENT_RATE_LIMITED.The standard error body.
- 451OPT_OUT_BLOCKED: the recipient opted out.The standard error body.
- 500Unexpected server error.The standard error body.
- 502CARRIER_ERROR: the carrier refused the SMS. The charge is refunded.The standard error body.
- 503CARRIER_UNAVAILABLE: the carrier could not be reached. Nothing was sent or charged; retry shortly. CARRIER_TIMEOUT: the carrier did not answer in time, so the code may or may not have reached the recipient. The verification is closed, so that code can never be checked, and the charge is refunded: start a new one.The standard error body.
Example
const { data: verification, error } = await honkio.verify.start({
from: '+1416XXXXXXX', // one of your HonkIO numbers
to: '+1613XXXXXXX',
appName: 'Acme',
})
if (error) throw new Error(error.message)
console.log(verification.id)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"
}'/v1/verify/{id}Get a verification
verify:rNode.js SDKhonkio.verify.get()Returns a single verification record by ID.
Requires verify:r.
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequiredpath | string |
Responses
200The verification.
Field Type Description idrequiredstring phone_numberrequiredstring from_numberrequiredstring statusrequiredstring - One of: pending | verified | expired | max_attempts
attemptsrequiredinteger code_lengthrequiredinteger app_namerequiredstring - Can be null
moderequiredstring TEST verifications are simulated: no SMS is sent, nothing is billed, and the code is always 000000 padded to code_length.
- One of: LIVE | TEST
cost_centsrequiredinteger Cost in cents CAD. On a TEST verification this is 0: nothing was charged.
expires_atrequiredstring - Format: date-time
verified_atrequiredstring - Format: date-time
- Can be null
created_atrequiredstring - Format: date-time
- 401Missing, invalid, revoked or expired API key.The standard error body.
- 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
- 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
- 404VERIFICATION_NOT_FOUND. A test key finds TEST verifications only.The standard error body.
- 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
- 500Unexpected server error.The standard error body.
Example
const { data, error } = await honkio.verify.get('VERIFICATION_ID')
if (error) throw new Error(error.message)
console.log(data.status, data.attempts_remaining)curl https://api.honkio.ca/v1/verify/ID \
-H "Authorization: Bearer mk_live_YOUR_KEY"/v1/verify/{id}/checkCheck a verification code
verify:wNode.js SDKhonkio.verify.check()Submit the OTP code the end-user received. Max 5 attempts. Accepts 4, 6, or 8 digit codes depending on how the verification was started.
Requires verify:w.
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequiredpath | string |
Request body
| Field | Type | Description |
|---|---|---|
coderequired | string | 4 to 8 digit OTP code |
Responses
200Code accepted: the verification is now verified.
Field Type Description idrequiredstring phone_numberrequiredstring from_numberrequiredstring statusrequiredstring - One of: pending | verified | expired | max_attempts
attemptsrequiredinteger code_lengthrequiredinteger app_namerequiredstring - Can be null
moderequiredstring TEST verifications are simulated: no SMS is sent, nothing is billed, and the code is always 000000 padded to code_length.
- One of: LIVE | TEST
cost_centsrequiredinteger Cost in cents CAD. On a TEST verification this is 0: nothing was charged.
expires_atrequiredstring - Format: date-time
verified_atrequiredstring - Format: date-time
- Can be null
created_atrequiredstring - Format: date-time
attempts_remainingrequiredinteger Always 0 on success.
- 401Missing, invalid, revoked or expired API key.The standard error body.
- 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
- 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
- 404VERIFICATION_NOT_FOUND. A test key finds TEST verifications only.The standard error body.
- 409VERIFICATION_ALREADY_VERIFIED.The standard error body.
- 410VERIFICATION_EXPIRED: start a new verification.The standard error body.
422VALIDATION_ERROR (not 4 to 8 digits) or VERIFICATION_INVALID_CODE, which carries attempts_remaining.
Field Type Description coderequiredstring Machine-readable error code, e.g. VALIDATION_ERROR.
messagerequiredstring Human-readable message in the request's locale (Accept-Language).
messageEnstring English message, always present alongside message.
messageFrstring French message, always present alongside message.
statusCoderequiredinteger The HTTP status, repeated in the body.
detailsany Present on some errors: an AJV validation array, or error-specific structured detail.
attempts_remaininginteger Wrong-code attempts left. Present only on VERIFICATION_INVALID_CODE.
- 429VERIFICATION_MAX_ATTEMPTS: five wrong codes; start a new verification. Also RATE_LIMITED at 100 requests per second.The standard error body.
- 500INTERNAL_ERROR: unexpected server error.The standard error body.
Example
const { data, error } = await honkio.verify.check('VERIFICATION_ID', { code: '123456' })
if (error?.name === 'VERIFICATION_INVALID_CODE') {
console.log(error.details) // { attempts_remaining: 4 }
} else if (data) {
console.log(data.status) // 'verified'
}curl -X POST https://api.honkio.ca/v1/verify/ID/check \
-H "Authorization: Bearer mk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "123456"
}'
HonkIO