---
title: "Send a double opt-in confirmation from a toll-free number"
method: POST
path: "/v1/compliance/opt-in-confirmations"
tags: ["Compliance / CASL"]
---

# Send a double opt-in confirmation from a toll-free number

`POST /v1/compliance/opt-in-confirmations`

## Request

- Base URL: `https://api.honkio.ca`
- URL: `https://api.honkio.ca/v1/compliance/opt-in-confirmations`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Texts the recipient a fixed confirmation from your verified toll-free number: "{brand_name}: reply YES to confirm you want text messages from us. Msg & data rates may apply. Reply STOP to opt out." (with `language: "fr"`: "{brand_name} : répondez OUI pour confirmer que vous voulez recevoir nos textos. Des frais de messagerie et de données peuvent s’appliquer. Répondez ARRET pour vous désabonner.").

Canadian toll-free messaging needs double opt-in, per sending number: until the recipient replies YES, Y, OUI or O to this number, sends to them from it are refused with 451 DOUBLE_OPT_IN_REQUIRED (each of your toll-free numbers asks for its own). The reply confirms the confirmation, records the double opt-in for this number, and fires `consent.double_opt_in_confirmed`. A STOP to this number withdraws it. Verification codes (POST /v1/verify) are exempt.

The recipient must already have an active consent (the first opt-in). The confirmation is billed as a normal message and expires after 7 days. Sending another from the same number replaces the pending one; at most 3 can be sent to one recipient in 24 hours, from any of your numbers. Live keys only.

Requires `compliance:w`.

## Request body

- object
  - `from` string, required: Your toll-free number (E.164) with an approved toll-free verification.
  - `to` string, required: The recipient (E.164, Canadian), who must already have an active consent.
  - `brand_name` string, required: The name the recipient knows you by, shown at the start of the text. Plain text: letters, numbers, spaces and . , ' & ! -, not a link.
  - `language` 'en' | 'fr': The language of the confirmation text.

## Response `201`

Sent: the confirmation, PENDING until the recipient replies YES.

- OptInConfirmation: A double opt-in confirmation sent from a toll-free number.
  - `id` string, required: oic_…
  - `status` 'PENDING' | 'CONFIRMED' | 'EXPIRED' | 'DECLINED', required: PENDING until the recipient replies YES (CONFIRMED), it lapses after 7 days or is replaced by a newer one (EXPIRED), or the recipient texts STOP (DECLINED).
  - `from` string, nullable, required: The toll-free number it was sent from.
  - `to` string, required: The recipient.
  - `brand_name` string, required
  - `language` 'en' | 'fr', required
  - `message_id` string, nullable, required: The confirmation text, as a message (GET /v1/messages/{id}).
  - `expires_at` string, date-time, required
  - `confirmed_at` string, date-time, nullable, required
  - `reply_message_id` string, nullable, required: The recipient's YES, as an inbound message.
  - `created_at` string, date-time, required

## Other responses

- `401`: Missing, invalid, revoked or expired API key.
- `402`: INSUFFICIENT_BALANCE: the balance cannot cover the send. Also PAYMENT_REQUIRED when a LIVE key is used before the first top-up.
- `403`: TOLL_FREE_NOT_VERIFIED (from has no approved toll-free verification), ACCOUNT_NOT_VERIFIED, LIVE_KEY_REQUIRED (test keys cannot send one), ALLOW_LIST_BLOCKED, DENY_LIST_BLOCKED or SENDING_PAUSED. Also FORBIDDEN when the key lacks compliance:w.
- `409`: PHONE_NUMBER_SUSPENDED: the from number is suspended for unpaid rent.
- `422`: INVALID_PHONE_NUMBER, NOT_A_TOLL_FREE_NUMBER (from is not one of your toll-free numbers), VALIDATION_ERROR (brand_name must be plain text, not a link), NON_CANADIAN_NUMBER, RESERVED_DESTINATION, UNDELIVERABLE_NUMBER or NOT_A_MOBILE_NUMBER. A refused send costs nothing.
- `429`: OPT_IN_CONFIRMATION_LIMIT (3 to one recipient in 24 hours), DAILY_LIMIT_REACHED, FANOUT_LIMIT_REACHED, NUMBER_RATE_LIMITED or RECIPIENT_RATE_LIMITED (Retry-After set on the two rate limits), or RATE_LIMITED at 100 requests per second.
- `451`: The recipient has no first opt-in: NO_CONSENT, CONSENT_EXPIRED or OPT_OUT_BLOCKED.
- `500`: Unexpected server error.
- `502`: CARRIER_ERROR: the carrier refused the send. Any charge is refunded and no confirmation is kept.
- `503`: CARRIER_UNAVAILABLE, CARRIER_THROTTLED or CARRIER_TIMEOUT: see POST /v1/messages. No confirmation is kept; send again.

---

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