---
title: "Create multi-channel verification"
method: POST
path: "/api/v1/verifications/multi-channel"
tags: ["Verifications"]
---

# Create multi-channel verification

`POST /api/v1/verifications/multi-channel`

## Request

- Base URL: `https://api.proof.holdings`
- URL: `https://api.proof.holdings/api/v1/verifications/multi-channel`
- Auth: HTTP bearer

Start one phone verification across several channels in a single call. Returns a setup block (deep link, QR, message) per channel; the first channel the user completes wins, sibling channels are cancelled and exactly one proof token is issued. Exactly one proof is billed, at the winning channel's completion — not one per channel, and nothing at creation; the HTTP rate limit charges one unit.

## Request body

- CreateMultiChannelVerificationRequest: Request body for creating a multi-channel verification group
  - `profile_id` string: The sub-account (project) this is for; its branding and templates are used for every message. An account-wide key may name any project of its account; a project-bound key acts for its own project only (naming another answers `403 profile_mismatch`). Omitted: the key's project, else the primary project.
  - `type` 'phone', required: Asset type (phone only in v1)
  - `identifier` string, required: The phone number to verify (E.164)
  - `channels` MultiChannelPhoneChannel[], required: Channels to offer, unique values. The first channel the user completes wins; siblings are cancelled and exactly one proof token is issued.
  - `external_user_id` string: Your user ID for grouping verifications
  - `client_metadata` object: Custom metadata to attach to every group member
  - `proof_expiry_days` integer: Per-request proof expiry override in days (1-365). Overrides account default.

## Response `201`

Multi-channel verification group created

- MultiChannelVerificationResponse: Multi-channel verification group with one setup block per channel
  - `group_id` string, required: Verification group ID (vg_ prefix)
  - `type` 'phone', required
  - `identifier` string, required
  - `status` 'pending' | 'verified' | 'failed' | 'expired' | 'revoked' | 'cancelled', required: Current status of the verification
  - `expires_at` string, date-time, required: When every channel challenge expires
  - `external_user_id` string
  - `client_metadata` object
  - `channels` MultiChannelChannelBlock[], required
    - `channel` 'whatsapp' | 'telegram' | 'sms', required: Phone verification channel available for multi-channel groups
    - `verification_id` string, required: MongoDB ObjectId
    - `status` 'pending' | 'verified' | 'failed' | 'expired' | 'revoked' | 'cancelled', required: Current status of the verification
    - `deep_link` string: Channel deep link (t.me / wa.me)
    - `qr_code` string: QR code data URL for the deep link
    - `qr_text` string: QR code rendered as UTF-8 text (terminal/agent display)
    - `message` string: Message the user must send on this channel
    - `instructions` string: Human-readable instruction for this channel
    - `phone_number` string: Number/handle the user sends the message to
    - `sms_message` string: SMS body to send (sms channel only)
    - `sms_dids` object: Per-region SMS DIDs with QR codes (sms channel only)
    - `suggested_region` 'americas' | 'europe' | 'israel': Suggested SMS region derived from the phone number (sms channel only)
  - `created_at` string, date-time, required

## Other responses

- `400`: Validation error
- `401`: Unauthorized
- `402`: card_required. Only once billing is live: a free account with no card on file that has used its included proofs and the 50-proof grace this month is refused new proof requests until a card is added (add_card_url). Proofs already issued keep working. The error carries add_card_url, used, included and hard_limit.
- `403`: profile_mismatch — a project-bound API key named another project (it acts for its own project only); profile_not_owned — the named project does not belong to the account (h-subaccount-branding-per-project)
- `429`: Rate limit or per-phone velocity exceeded

---

[API](https://skmtc.dev/proof/apis/proof-holdings-api.md) · [All operations](https://skmtc.dev/proof/apis/proof-holdings-api/llms.txt) · [OpenAPI document](https://skmtc.dev/proof/apis/proof-holdings-api/revisions/b15f506de696?raw)
