Start a verification
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.
bearerAuthAuthorizationBearer <token>A secret API key from the dashboard: coss_live_… for production environments, coss_test_… for sandbox environments.
Idempotency-Key?stringMakes 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.
1 <= length <= 256Coss-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.
"2026-10-10"application/json- body
- body
- …
to*stringWhere 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.
1 <= length <= 320channel?stringsms or email. Default: sms for a phone number, email for an address.
"sms""email"ip?stringThe end user's IP address. The fraud guard uses it (velocity, Tor); recommended.
length <= 64user_id?stringYour id for the end user, for the fraud guard's velocity and your Risk lists.
1 <= length <= 256tags?array<>Up to 10 tags.
items <= 10The verification, pending, with the send that just went out.
application/json- response
- response
- …
object*"verification""verification"id*stringchannel*string"sms""email"to*stringcountry*|ISO 3166 country of a phone number.
status*stringpending 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).
"pending""approved""expired""canceled""failed""blocked"failure*|Why it failed.
reasons*array<>Why it was blocked (empty otherwise).
attempts*integerWrong codes checked so far.
max_attempts*integersends*array<>Each time the code was sent.
tags*array<>sandbox*booleanMade in a sandbox environment: simulated, and the code is always zeros.
expires_at*stringdate-timeapproved_at*|date-timecreated_at*stringdate-timeimport { 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"}