---
title: "Send a verification code"
method: POST
path: "/v1/verify/verifications"
tags: ["Verify"]
---

# Send a verification code

`POST /v1/verify/verifications`

Generate a one-time code, deliver it to the recipient, and store only
its hash. Check the user-typed code with
POST /v1/verify/verifications/{verificationId}/check.

Re-POSTing for the same (channel, to) while a verification is active
RESENDS a fresh code on the existing verification (200 with
`resend: true`) instead of creating a new one; resends are limited to
one per 60 seconds (429 with `retryAfterSeconds` inside the cooldown).
The stored brandName/codeLength/ttlMinutes win on a resend.

Codes deliver by SMS from a phone number on your account (`from`
optional when you own exactly one SMS-enabled number) and the message
uses a fixed template. Each accepted send bills one verification fee
plus the standard message rate.

## Request body

- object
  - `channel` 'sms', required — SMS-only for now.
  - `to` string, required — E.164 phone number.
  - `from` string — The SMS-enabled number on your account to send from. Defaults to your only SMS number.
  - `brandName` string — Your app or business name, rendered in the message. Defaults to your account name. Letters, numbers, and basic punctuation only.
  - `codeLength` integer
  - `ttlMinutes` integer

## Response `200`

Active verification found: a fresh code was resent (`resend: true`).

- Verification — A managed OTP verification. The code itself is never returned or stored (hash only).
  - `id` string
  - `status` 'pending' | 'approved' | 'expired' | 'max_attempts_reached' | 'canceled' | 'delivery_failed'
  - `channel` 'sms'
  - `to` string
  - `expiresAt` string, date-time
  - `attempts` integer
  - `maxAttempts` integer
  - `sendCount` integer — Accepted deliveries (initial send + resends); each bills one verification fee.
  - `lastSentAt` string, date-time, nullable
  - `createdAt` string, date-time
  - `resend` boolean — Present on create responses: true when an active verification was resent instead of created.

## Other responses

- `201` — Verification created and the code sent.
- `400` — Invalid request
- `401` — Unauthorized
- `403` — Verifications require usage-based billing.
- `404` — The 'from' number is not an SMS-enabled number on this account.
- `409` — The recipient has opted out of messages from your number.
- `422` — Verifications need an SMS-enabled number on your account; add one first.
- `429` — Resend cooldown or a send cap was hit; `retryAfterSeconds` says when to retry.

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/f81ca70ea6b9/schema)
