Skip to content

API v1

API reference

Buy numbers and read codes from your own systems. Same prices, balance and automatic refunds as the dashboard.

Authentication

Create a key in Dashboard → API. Send it on every request. Keep it on your server — it can spend your balance. Making a new key turns off the old one immediately.

Authorization: Bearer cove_live_xxxxxxxxxxxxxxxx
Base URL: https://www.covesms.com/api/v1

Endpoints

  • GET/balanceYour balance and currency.
  • GET/countriesCountries with numbers in stock right now, with the number of apps each.
  • GET/services?country=usApps in stock for one country: code, name, price and stock.
  • POST/numbersBuy a number. Body: service, country, optional max_price. Returns 201 with the number.
  • GET/numbers/{id}One number’s status and every SMS it received. Poll every 3–5 seconds, or use the webhook.
  • GET/numbers?status=active&limit=50Numbers bought through the API, newest first. Paginate with before=<created_at>.
  • POST/numbers/{id}/cancelCancel and refund a number with no SMS. Allowed from cancelable_at (2 minutes after purchase).
  • POST/numbers/{id}/resendAsk for another SMS on an open number that already got one. Free.
  • POST/numbers/{id}/finishRelease a number that got its code, before the reservation ends.

Example: buy a number

curl -X POST https://www.covesms.com/api/v1/numbers \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service":"whatsapp","country":"us","max_price":3.50}'

HTTP/1.1 201 Created
{
  "id": "num_8f2c41",
  "phone": "+12135550147",
  "service": "whatsapp",
  "country": "us",
  "price": 2.89,
  "currency": "USD",
  "status": "waiting",
  "created_at": "2026-10-14T15:02:11Z",
  "cancelable_at": "2026-10-14T15:04:11Z",
  "expires_at": "2026-10-14T15:22:11Z",
  "sms": []
}

Statuses

waiting
Open for 20 minutes, waiting for an SMS.
received
At least one SMS arrived. The code is in sms[].code, the full text in sms[].text.
finished
You released the number after getting the code.
canceled
You canceled it before any SMS. Refunded.
expired
No SMS within 20 minutes. Refunded automatically.

Webhooks

Set an HTTPS URL in Dashboard → API. When a number bought through the API receives an SMS, we POST an sms.received event, retrying up to 3 times. Reply with any 2xx.

Every request carries X-Signature: t=<unix>,v1=<hex> — the HMAC-SHA256 of "<t>.<raw body>" with your signing secret. Reject timestamps older than 5 minutes.

// Node.js
import crypto from "node:crypto";

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected), b = Buffer.from(parts.v1 ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);   // compare lengths first
}

Errors

Errors return an HTTP status and { "error": { "code", "message" } }.

HTTPCodeMeaning
401invalid_api_keyMissing, wrong or revoked key
402insufficient_balanceBalance too low; needed shows the price
409price_above_maxLive price is above your max_price; price shows the live price
400no_numbersOut of stock; you weren’t charged
400too_earlyCancel before cancelable_at; wait_seconds says how long
400already_closedNumber already canceled, expired or finished
403account_suspendedContact support
429rate_limitedMore than 120 requests in a minute
503provider_unavailableTemporary carrier issue; not charged — retry shortly

Limits and rules

  • • 120 requests per minute per key. Poll a number no faster than every 3 seconds.
  • • One number per verification, SMS only, reserved 20 minutes.
  • • Prices move with supply — read them from /services or send max_price.
  • • Use the API only for your own accounts, or as a reseller for customers who follow our Acceptable Use Policy. Bulk sign-ups, spam and getting around identity checks close the account.