Put the full activation lifecycle in your test workflow.
A VerifyOrbit key lets your application inspect supported routes, place a service-specific order and read the provider's latest outcome. Treat a received code, an unresolved order and a confirmed refund as different states.
# Example response; availability and price change by route curl -X POST https://verifyorbit.com/api/v1/activations \ -H "Authorization: Bearer $VERIFYORBIT_KEY" \ -H "Content-Type: application/json" \ -d '{"service":"openai","country":"us"}' { "id": "5f0c2a9e4b1d7c3a9e2f6b10", "status": "pending", "phone": "+12015550123", "price_cents": 41, "expires_at": "2026-10-30T10:32:00+00:00" }
Authentication
Generate a key in Dashboard → Developers and store it in a server-side secret store. The vo_live_ value appears once. Pass it as an authorization header, never in a public browser URL:
Authorization: Bearer vo_live_xxxxxxxxxxxxxxxxxxxx
The pay-as-you-go rate is 120 requests per minute. Read /api/v1/balance for the limit currently assigned to your account, and back off on a 429 response.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/balance | Available USD cents and active request quota |
| GET | /api/v1/countries | Country identifiers and calling prefixes |
| GET | /api/v1/services?country=us | Current route selection for one country |
| GET | /api/v1/price?service=telegram&country=gb | Quote the exact app-country pair |
| POST | /api/v1/activations | Open an order with {"service","country"} |
| GET | /api/v1/activations/{id} | Read the latest state, SMS and code |
| POST | /api/v1/activations/{id}/retry | Ask the same order for another SMS when allowed |
| POST | /api/v1/activations/{id}/finish | Mark a completed code flow finished |
| POST | /api/v1/activations/{id}/cancel | Request an unused cancellation; check the later refund state |
| GET | /api/v1/numbers | List the account's renewable lines |
| GET | /api/v1/numbers/{id}/messages?since_id=0 | Read the line's inbox after a message ID |
Activation statuses
An order can begin as pending, move to received and then finished, or end as cancelled or expired. A terminal status alone does not prove money was returned. Inspect the separate refunded field and allow for provider reconciliation.
Errors
Handle the machine-readable error.code, rather than matching the English message. Common cases are invalid_api_key (401), insufficient_funds (402 with shortfall_c), out_of_stock, too_early or no_retry (409), account_locked (423), and rate_limited (429).
Node.js example
const API = "https://verifyorbit.com/api/v1";
const H = { Authorization: `Bearer ${process.env.VERIFYORBIT_KEY}`, "Content-Type": "application/json" };
const act = await (await fetch(`${API}/activations`, { method: "POST", headers: H,
body: JSON.stringify({ service: "telegram", country: "us" }) })).json();
for (;;) {
const a = await (await fetch(`${API}/activations/${act.id}`, { headers: H })).json();
if (a.status === "received") { console.log(a.code); break; }
if (["cancelled", "expired", "failed"].includes(a.status)) throw new Error("Order ended; check refunded status");
await new Promise(r => setTimeout(r, 4000));
}
More: how SMS verification works and what to check when a code does not arrive.
Connect a supported route to your workflow.
Create a key, quote the app-country pair and handle each provider outcome explicitly.