Purchase a number

POST /v1/numbers

Supports the Idempotency-Key header: a retried purchase replays the original 201.

Send your API key as a bearer token: Authorization: Bearer ssms_sk_.... Test keys run this endpoint against the sandbox; see Authentication for key modes and scopes.

Headers

NameTypeRequiredDescription
Idempotency-KeystringNoMakes retries safe for 24 hours: the same key and body replays the original successful response (with Idempotent-Replayed: true); a different body returns 409. Failed requests release the key. At most 255 characters.

Request body

JSON (Content-Type: application/json).

FieldTypeRequiredDescription
phone_numberstringYesExample: +15005550132.
customer_idstringNoOptional: assign the number to one of your customers
registration_idstringNoOptional (live numbers): the registration this number should send for. Without it the number follows your account's registration.

Responses

StatusMeaningBody
201Number purchasedNumber
401Missing, malformed, or revoked API keyError
402Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or chargedError
409Idempotency conflictError
429Rate limit or quota exceededError

201: Number fields

FieldTypeDescription
idstringExample: +15005550132.
objectnumber
phone_numberstring
statusactive, released
modetest, live
created_atstring (date-time)
customer_idstringThe customer this number is assigned to Nullable.
labelstringNullable.
tagsarray of string
poolsarray of stringPool ids
senderobjectHow the number stands with the carriers. null on sandbox numbers and on numbers that need no registration (toll-free, Canadian). Only an active number can text anyone; in every other state it can text only your verified numbers. Nullable.
sender.statetest_only, pending, active, action_neededtest_only: no registration submitted. pending: a registration is in review, or approved and being linked. active: linked to an approved registration. action_needed: see reason.
sender.registration_idstringThe registration it is (being) linked to Nullable.
sender.reasonstringWhat to do, in plain words, when state is action_needed Nullable.
sender.updated_atstring (date-time)

Errors

StatusWhen
401Missing, malformed, or revoked API key
402Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or charged
409Idempotency conflict
429Rate limit or quota exceeded

Every error has the same JSON shape, and request_id matches the X-Request-Id response header. Errors lists every code and what to do about it.

json
{
  "error": {
    "code": "invalid_request",
    "message": "What went wrong, in plain words.",
    "param": "the_field",
    "request_id": "req_a1B2c3D4e5F6g7H8"
  }
}

Idempotency

Send an Idempotency-Key header to make retries safe. For 24 hours the same key with the same body replays the original successful response (with Idempotent-Replayed: true); the same key with a different body returns 409. A failed request releases its key.

Examples

curl

bash
curl -X POST "https://api.joinsimplesms.com/v1/numbers" \
  -H "Authorization: Bearer $SIMPLESMS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2f0e-order-1042" \
  -d '{
  "phone_number": "+15005550132"
}'

Node.js

javascript
import { SimpleSMS } from 'joinsimplesms'; // npm install joinsimplesms

const sms = new SimpleSMS(process.env.SIMPLESMS_API_KEY);

const number = await sms.numbers.buy('+14155550132');

console.log(number.phone_number);

Python

python
import os
from joinsimplesms import SimpleSMS  # pip install joinsimplesms

client = SimpleSMS(os.environ["SIMPLESMS_API_KEY"])

number = client.numbers.buy("+14155550132")

print(number["phone_number"])