Developer API · Reference
Phone numbers & SMS, one REST call away.
Everything bills pay-as-you-go from your CrowPhone credit balance. All endpoints accept and return JSON. Get a key on the Developers page, or start at the overview.
Authentication
Pass your key as a Bearer token on every request (except GET /countries). Keys start with cp_live_, are shown once at creation, and can be rotated anytime from the Developers page.
Authorization: Bearer cp_live_your_key_here
Endpoints
GET/api/v1/countriesno auth
Available countries with monthly number pricing, per-SMS rates and capabilities.
Parameters
None.
Sample request
curl https://www.crowphone.com/api/v1/countries
Sample response · 200
{
"countries": [
{
"code": "SE",
"name": "Sweden",
"monthly_price": 4.60,
"sms_receive_price": 0.03,
"sms_send_price": 0.04,
"capabilities": { "receive_sms": true, "send_sms": true, "voice": true }
}
]
}POST/api/v1/numbers
Buy a number, charged from your balance. PH/SE are mobile-class — best for receiving verification codes, and the only ones that can send SMS (US/CA are receive-only).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
country | body | string | optional | ISO country code (see GET /countries). Defaults to US — or SE when must_send_sms is true. |
months | body | integer | optional | Rental length in months, 1–12. Default 1. |
must_send_sms | body | boolean | optional | Set true if you need outbound SMS: receive-only countries are rejected up front, and with no country given we pick SE for you. |
Sample request
curl -X POST https://www.crowphone.com/api/v1/numbers \
-H "Authorization: Bearer cp_live_..." \
-H "Content-Type: application/json" \
-d '{"must_send_sms": true, "months": 1}'Sample response · 200
{
"id": "0f6f4a4e-…",
"number": "+46700900123",
"country": "SE",
"months": 1,
"price": 3.22,
"expires_at": "2026-10-07T12:00:00.000Z",
"balance": 46.78,
"capabilities": { "receive_sms": true, "send_sms": true, "voice": true },
"notes": [
"Deliverability is strongest for same-region traffic (e.g. SE → EU). Note: US/CA destinations only accept registered US/CA senders — international numbers cannot text them, and such sends are rejected up front without charge."
]
}GET/api/v1/numbers
List your app's active numbers.
Parameters
None.
Sample request
curl https://www.crowphone.com/api/v1/numbers \ -H "Authorization: Bearer cp_live_..."
Sample response · 200
{
"numbers": [
{
"id": "0f6f4a4e-…",
"number": "+46700900123",
"country": "SE",
"expires_at": "2026-10-07T12:00:00.000Z",
"created_at": "2026-09-07T12:00:00.000Z",
"capabilities": { "receive_sms": true, "send_sms": true, "voice": true }
}
]
}DELETE/api/v1/numbers/:id
Release a number immediately. No refund for unused time — release when you're done with it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | required | The number's id from POST /numbers or GET /numbers. |
Sample request
curl -X DELETE https://www.crowphone.com/api/v1/numbers/0f6f4a4e-… \ -H "Authorization: Bearer cp_live_..."
Sample response · 200
{
"released": true,
"number": "+46700900123"
}POST/api/v1/messages
Send an SMS from one of your numbers. Priced per 160-character segment (70 for emoji/unicode) at the destination country's rate; carrier-reported failures are refunded automatically.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | body | string | required | One of your app's active numbers, E.164 (e.g. +46700900123). Must be send-capable — US/CA numbers are rejected. |
to | body | string | required | Destination number, E.164. |
body | body | string | required | Message text, up to 1,600 characters. Long messages bill as multiple segments. |
Sample request
curl -X POST https://www.crowphone.com/api/v1/messages \
-H "Authorization: Bearer cp_live_..." \
-H "Content-Type: application/json" \
-d '{"from": "+46700900123", "to": "+46701234567",
"body": "Your order shipped"}'Sample response · 200
{
"id": "b3e2c1d0-…",
"sid": "SM8f3…",
"from": "+46700900123",
"to": "+46701234567",
"segments": 1,
"price": 0.04,
"balance": 46.74,
"status": "queued"
}
// Sends to US/CA destinations return 400: those carriers only accept
// registered US/CA senders, so no international number can text them.GET/api/v1/messages
List messages across your numbers, newest first. Use this for polling if you don't set a webhook.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
number | query | string | optional | Filter to one of your numbers, E.164. |
direction | query | string | optional | "inbound" or "outbound". Omit for both. |
limit | query | integer | optional | Max results, 1–100. Default 50. |
Sample request
curl "https://www.crowphone.com/api/v1/messages?direction=inbound&limit=20" \ -H "Authorization: Bearer cp_live_..."
Sample response · 200
{
"messages": [
{
"id": "a1f9e8d7-…",
"number": "+46700900123",
"from": "+46701234567",
"to": "+46700900123",
"body": "Thanks!",
"direction": "inbound",
"price": 0.03,
"created_at": "2026-09-07T12:05:00.000Z"
}
]
}GET/api/v1/balance
Your current credit balance.
Parameters
None.
Sample request
curl https://www.crowphone.com/api/v1/balance \ -H "Authorization: Bearer cp_live_..."
Sample response · 200
{
"balance": 46.74,
"currency": "USD"
}Errors
Errors are JSON with a human-readable message. Anything refundable is refunded before the error is returned.
400 | Invalid parameters — the message field says exactly what to fix. |
401 | Missing, malformed, revoked, or unknown API key. |
402 | Insufficient balance. The message includes the exact cost. Top up at /topup. |
403 | Account not eligible (e.g. API unlocks at $50 in lifetime top-ups). |
404 | Resource not found, or not owned by this app. |
429 | Daily send cap reached for this app (default 500/day — open a support ticket to raise it). |
502 | Carrier rejected the action. Any charge is already refunded — the message says "You have not been charged." |
Inbound message webhooks
Set a webhook URL on your app and every text received by your numbers is POSTed to it within seconds. Verify the X-Crowphone-Signature header: it's sha256=HMAC-SHA256(raw_body, webhook_secret) using the secret shown when you created the app. No webhook? Poll GET /api/v1/messages instead.
POST https://yourapp.com/webhooks/crowphone
X-Crowphone-Signature: sha256=3f1a…
{
"type": "message.received",
"data": {
"number": "+46700900123",
"from": "+14155550123",
"body": "Your code is 123456",
"received_at": "2026-09-07T04:20:00.000Z"
}
}Good to know
- Receiving verification codes: strict apps (WhatsApp, Google, Discord) often refuse virtual numbers. Mobile-class numbers (PH, SE) have the best acceptance odds; US/CA numbers are VoIP-class and get refused more.
- Sending: US/CA numbers can't send SMS (carrier registration rules) — send from PH/SE numbers, or pass
"must_send_sms": truewhen buying and we'll pick one for you. - Deliverability: European and most open-market destinations deliver reliably (e.g. SE → EU). Some destinations require carrier-registered senders — US & Canada (rejected up front, no charge) and the Philippines (rejected by the carrier, refunded automatically) are the known ones. Receiving works on every line from anywhere.
- Fair billing: failed sends and undelivered messages are refunded automatically. Unanswered inbound calls cost nothing.
- Limits: 500 outbound SMS per app per day by default — open a ticket to raise it.
- Access: creating an API app requires $50 in lifetime top-ups. It's spendable credit, not a fee — it keeps the API spam-free.
- Voice calling via API is coming soon; calls work today in the browser dialer.
API access unlocks at $50 in lifetime top-ups — all of it spendable credit for numbers and messages (and $50+ earns +12% bonus credits).
