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

# Create a verification

`POST /v1/verify/verifications`

## Request

- Base URL: `https://us1.platform.bird.com`
- URL: `https://us1.platform.bird.com/v1/verify/verifications`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `bird_session`

Creates a verification and sends the recipient a one-time passcode. Provide an email address, a phone number, or both in `to`. The service sends over one channel at a time and moves to the next planned channel if delivery fails.

Calling this again for the same recipient reuses the verification in progress. During the resend cooldown, it returns the current state without sending, so nothing is charged and no send budget is spent. After the cooldown, it sends a fresh passcode, and that send draws on the recipient's hourly send cap exactly as a new verification does, so repeated resends can exhaust the cap and return `429` for the rest of that rolling hour. [Abuse guardrails](/docs/guides/verify/sending-verifications#abuse-guardrails) gives the figures.

The `200` response contains the current state, never the passcode. Submit the recipient's passcode with [Check a verification](/docs/api/reference/create-verification-check) before `expires_at`. An invalid recipient returns `422`; exceeding the send rate limit returns `429`.

## Headers

- `Idempotency-Key` string
- `X-Workspace-Id` string
- `X-Organization-Id` string

## Request body

- VerificationCreateRequest
  - `to` VerificationTo, required: The recipient to verify. Provide an `email`, a `phone_number`, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
    - `email` string, email: The recipient's email address. Case does not matter; the address is lowercased before use.
    - `phone_number` string: The recipient's phone number in E.164 format, with the leading `+` and country code (for example `+15551234567`). A number in any other format is rejected as an invalid recipient (`422`).
  - `options` VerificationOptions: Per-request overrides applied to this verification only.
    - `code_length` integer: Passcode length for this verification. Omit to use the configured length.
    - `channels` VerificationChannel[]: Reorder or narrow the delivery channels for this request. List channel names in the order to try them; a channel you omit is not used for this request, and a channel not already enabled for the recipient is ignored. A list that leaves no usable channel fails the request with `422`. Omit the field to use the configured order.
    - `language` string: A language tag in BCP-47 form, for example `en` or `pt-BR`.
  - `metadata` object: Optional key/value pairs to attach to the verification, for example a correlation id. Returned on the verification.

## Response `200`

The verification's current state, whether newly opened or reused.

- Verification
  - `id` string, required
  - `status` 'pending' | 'verified' | 'failed' | 'expired' | 'canceled' | 'blocked', required: The verification's current state: - `pending`: Awaiting a correct passcode. - `verified`: A correct passcode was submitted. - `failed`: The verification cannot be completed. Either too many incorrect passcodes were submitted, or no planned channel could deliver one. Read `reason` to tell those apart. - `expired`: The validity window elapsed before a correct passcode. - `canceled`: The verification was canceled before completion. - `blocked`: A fraud or abuse control stopped the verification.
  - `reason` string: Why a verification session reached its final state without succeeding: `attempts_exhausted` (too many incorrect passcodes), `ttl_elapsed` (the time window elapsed before a correct passcode), or `undeliverable` (no planned channel could deliver a passcode, so the recipient never had one to submit). Open enum: new reasons may be added over time, so treat any unrecognized value as a future reason rather than an error.
  - `to` VerificationTo, required: The recipient to verify. Provide an `email`, a `phone_number`, or both; at least one is required. The addresses also identify the verification: a check must supply exactly the set used on the create call, so a verification created with both addresses is not found by either one alone.
    - `email` string, email: The recipient's email address. Case does not matter; the address is lowercased before use.
    - `phone_number` string: The recipient's phone number in E.164 format, with the leading `+` and country code (for example `+15551234567`). A number in any other format is rejected as an invalid recipient (`422`).
  - `channels` VerificationChannelEntry[], required: The channels this verification uses to deliver the passcode, in attempt order: the first entry is tried first and later entries are fallbacks. An email recipient is verified over email; a phone recipient is verified over the phone channels enabled for its destination country, in the order that country's configuration sets.
    - `channel` string, required: The channel a passcode is delivered over. Open enum: new channels may be added over time, so treat any unrecognized value as a future channel rather than an error.
  - `last_channel` string, nullable: The channel the most recent passcode was sent on, or `null` before the first send. Open enum; new channels may be added over time, so treat any unrecognized value as a future channel rather than an error.
  - `metadata` object: The key/value pairs attached when the verification was created.
  - `expires_at` string, date-time, required: When the verification expires if no correct passcode is submitted first. After this time its status reports `expired`.
  - `verified_at` string, date-time, nullable: When the verification was completed, or `null` if it is not yet verified.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `402`: Insufficient balance
- `403`: Insufficient permissions
- `404`: Resource not found
- `422`: The request has invalid field values, violates a business rule, or carries a query parameter the endpoint does not declare. Field validation errors use `type: validation_error` and include the affected fields in `details`. Business-rule errors identify the failed rule in `type`.
- `429`: Rate limit exceeded
- `500`: Internal server error
- `503`: The service is temporarily unavailable. If `Retry-After` is present, wait for that delay before retrying; otherwise, retry with exponential backoff. Reuse the same idempotency key and request when retrying a mutation.

---

[API](https://skmtc.dev/messagebird/apis/bird-api.md) · [All operations](https://skmtc.dev/messagebird/apis/bird-api/llms.txt) · [OpenAPI document](https://skmtc.dev/messagebird/apis/bird-api/revisions/3e2a50466454?raw)
