Start a verification

POST
/v1/verifications

Sends a one-time code to a phone number (SMS) or an email address and returns the verification, pending until you check the code the end user typed (POST /v1/verifications/check). Starting again for the same destination while it is pending sends a new code (the earlier one stops working), up to 5 times. Before a new verification costs anything, the fraud guard checks it (your Risk lists, premium-rate numbers, Tor, and velocity per IP, user, number range and country, with how often their codes are entered): a blocked one is stored with its reasons and nothing is sent. Pass the end user's ip (and your user_id) so it can tell them apart. SMS codes come from coss.com's shared numbers unless the environment's Verify settings name one of your own; email codes from your sender, else coss.com's. Sandbox (coss_test_…) keys deliver nothing and the code is always zeros.

Authorization

bearerAuth
headerAuthorizationBearer <token>

A secret API key from the dashboard: coss_live_… for production environments, coss_test_… for sandbox environments.

Header Parameters

Idempotency-Key?string

Makes retries safe: a repeated request with the same key and body returns the original verification instead of sending another code, for 24 hours. 1-256 characters.

Length1 <= length <= 256
Coss-Version?"2026-10-10"

The API version (a date) to use for this request. Defaults to your organization's version, pinned to the latest one when it first used the API and upgraded from the dashboard. The SDK always sends the version it was built for.

Value in"2026-10-10"

Request Body

application/json
  1. body
to*string

Where the code goes: a mobile number in E.164 form, or an email address. A pending verification to the same destination and channel is reused: its code is sent again.

Length1 <= length <= 320
channel?string

sms or email. Default: sms for a phone number, email for an address.

Value in"sms""email"
ip?string

The end user's IP address. The fraud guard uses it (velocity, Tor); recommended.

Lengthlength <= 64
user_id?string

Your id for the end user, for the fraud guard's velocity and your Risk lists.

Length1 <= length <= 256
tags?array<>

Up to 10 tags.

Itemsitems <= 10

Response Body

The verification, pending, with the send that just went out.

application/json
  1. response
object*"verification"
Value in"verification"
id*string
channel*string
Value in"sms""email"
to*string
country*|

ISO 3166 country of a phone number.

status*string

pending until the right code is checked (approved) or it ends: expired, canceled, failed (too many wrong codes, or the code couldn't be sent) or blocked (the fraud guard stopped it before anything was sent).

Value in"pending""approved""expired""canceled""failed""blocked"
failure*|

Why it failed.

reasons*array<>

Why it was blocked (empty otherwise).

attempts*integer

Wrong codes checked so far.

max_attempts*integer
sends*array<>

Each time the code was sent.

tags*array<>
sandbox*boolean

Made in a sandbox environment: simulated, and the code is always zeros.

expires_at*string
Formatdate-time
approved_at*|
Formatdate-time
created_at*string
Formatdate-time
import { Coss } from "coss";const coss = new Coss({  apiKey: process.env.COSS_API_KEY,  baseUrl: "https://api.coss.com",});const { data, error } = await coss.verify.start({  to: "+14155550199",  ip: "203.0.113.7",  user_id: "user_42",});
{  "object": "verification",  "id": "vrf_01k8e2m4q2f3e9v6t5r1n0p8yz",  "channel": "sms",  "to": "+14155550199",  "country": "US",  "status": "pending",  "failure": null,  "reasons": [],  "attempts": 0,  "max_attempts": 5,  "sends": [    {      "channel": "sms",      "route": "shared_number",      "sms_id": "sms_01k8e2m4q2f3e9v6t5r1n0p8yz",      "email_id": null,      "created_at": "2026-11-10T12:00:00.000Z"    }  ],  "tags": [],  "sandbox": false,  "expires_at": "2026-11-10T12:10:00.000Z",  "approved_at": null,  "created_at": "2026-11-10T12:00:00.000Z"}