Buy a phone number
https://api.norreach.app/v1/phone-numbersAsks to buy a number from GET /phone-numbers/available, under the owner's rules: the key needs the numbers:buy scope (in no preset — tick it on purpose) and an owner's or admin's role; the workspace's DAILY LIMIT for numbers bought through the API and its MONTHLY-COST CEILING are enforced by the database, so parallel requests can't race past them (429 number_cap_reached with reason and the caps — defaults 2 a day and 20.00 USD a month, changed by owners and admins in Settings › API & webhooks). The purchase WAITS IN APPROVALS (202, approval_key) until a person approves it — in the app, or with approvals:decide + numbers:buy — and is bought at that moment through the app's own purchase, every check run again (the number still on sale and its price, the caps, the country's rules and business verification, the role, the outreach pause). An owner can switch on "API may buy numbers without approval"; then it's bought at once (201, or 202 while the order settles). The same number asked for again while it waits answers the waiting request. 409 with reason number_taken / price_unconfirmed / verification_required / purchase_failed; nothing is ever charged on a refusal. Releasing a number is done in the app only. dry_run=true checks everything and buys nothing. Fires number.purchased.
curl -X POST "https://api.norreach.app/v1/phone-numbers" \
-H "Authorization: Bearer $NORREACH_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"number": "+46812345679",
"country": "SE",
"type": "local",
"label": "Stockholm sales"
}'{
"object": "number_purchase",
"number": "+46812345679",
"status": "awaiting_approval",
"dry_run": false,
"approval_key": "number_buy:2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"phone_number": null,
"monthly_price": {
"amount_minor": 300,
"currency": "USD"
},
"caps": {
"daily_limit": 2,
"bought_today": 0,
"monthly_ceiling": {
"amount_minor": 2000,
"currency": "USD"
},
"committed_this_month": {
"amount_minor": 0,
"currency": "USD"
}
},
"note": "Waiting in Approvals — nothing is bought until an owner or admin approves it."
}Authorizations
Bearer authentication: send Authorization: Bearer <key>, with an API key or an OAuth access token. The key needs the scope numbers:buy. API keys and scopes
Query parameters
Run every check and return what would happen, changing nothing.
Headers
Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.
Body
application/json
E.164, from GET /phone-numbers/available.
localmobiletollfreeResponse
202application/json— Buy a phone number
awaiting_approval = waiting in Approvals (approval_key); bought = yours now (phone_number); pending = the order is still settling; would_buy / would_wait = a dry run.
awaiting_approvalboughtpendingwould_buywould_waitShow child attributesHide child attributes
Show child attributesHide child attributes
Show child attributesHide child attributes
Errors
Errors are application/problem+json with a stable code.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request couldn't be read. |
| 400 | unknown_field | The request has a field this operation doesn't know. |
| 400 | idempotency_key_required | This operation needs an Idempotency-Key header. |
| 401 | unauthorized | A valid API key is required. |
| 403 | insufficient_scope | This API key doesn't have the scope this operation needs. |
| 403 | feature_not_enabled | The API isn't switched on for this workspace. |
| 403 | role_forbidden | The key's creator's role can't do this. |
| 409 | idempotency_in_progress | A request with this Idempotency-Key is still running. |
| 409 | conflict | That conflicts with the current state. |
| 409 | outreach_paused | Outreach is paused for this workspace. |
| 413 | too_large | The request body is too large. |
| 422 | validation_failed | The request has invalid fields. |
| 422 | idempotency_mismatch | This Idempotency-Key was used with a different request. |
| 429 | rate_limited | Too many requests. Slow down and try again. |
| 429 | number_cap_reached | The workspace's limit for buying numbers through the API is reached. |
| 500 | server_error | Something went wrong on our side. |
| 503 | unavailable | The API isn't available right now. Try again shortly. |