Channelsv4

Purchase Blooio numbers

POST/channels/blooio/purchases

Purchase one or more Blooio lines. Purchases are asynchronous and billable: the call charges the organization's credit balance, then its default payment method, and returns a purchase_id; the lines are provisioned when Stripe confirms the invoice, at which point a number.purchase.completed webhook fires (or number.purchase.failed). A card requiring 3DS/SCA returns status: action_required with an action_url, and also emits number.purchase.action_required.

Idempotency is required — send a unique Idempotency-Key header; replaying the same key returns the same purchase rather than charging twice.

Rules enforced server-side (identically to the dashboard): without a saved payment method, the organization's credit must cover the purchase in full (else 402 no_payment_method, and nothing is charged); shared plans are limited to one line per organization (409 shared_number_limit); and a single order may not exceed the per-order line cap (400 line_limit_exceeded, default 10 — apply for an increase in the dashboard Limits tab). Requested area codes that are out of stock incur a custom area-code fee and open a provisioning ticket; in-stock codes are assigned immediately with no custom fee.

Custom requests. For anything the pool can't fill automatically (installing your own eSIM, porting in a number, a number from another country), send custom_requests: one entry per line, matched to lines by position like area_codes. Each line with a custom request is charged the one-time custom fee, is never assigned automatically, and opens a provisioning ticket carrying your notes. The line stays pending (phone_number: null, with a ticket_id in the purchase status) until Blooio staff provision it. Read the ticket with GET /v4/tickets/{ticketId}.

Requires the number purchase API feature to be enabled, and the numbers:manage scope for OAuth apps.

Headers

AuthorizationRequiredstring

Your API key, sent as a bearer token: Authorization: Bearer <api_key>. Editing this stays in sync with the API key box on the right.

Bearer
Idempotency-KeyRequiredstring

Unique key that makes the billable purchase safe to retry.

Body parameters

JSON
planRequiredstring

Plan id to purchase (determines shared / dedicated / inbound). Use the specific id, not the tier name — e.g. dedicated_com or dedicated_ent, not dedicated (which returns invalid_plan).

"shared_nc""shared_com""dedicated_com""dedicated_ent""inbound_basic"
quantityoptionalinteger

Number of new lines (dedicated/inbound). Shared is always 1.

area_codesoptionalstring[]

Preferred 3-digit US area codes (dedicated/inbound). Out-of-stock codes incur a custom fee and open a ticket.

zip_codesoptionalstring[]

Preferred ZIP codes (dedicated/inbound), used when an area code is not specified.

custom_requestsoptionalobject | null[]

Per-line custom provisioning requests (dedicated/inbound only), matched to lines by position. An object marks that line for manual provisioning by Blooio staff; null (or no entry) leaves the line on normal fulfillment. May not have more entries than quantity. Each custom line is charged the one-time custom fee and opens a provisioning ticket. Notes are stored as sent and shown on the ticket to your organization and Blooio staff.

Array of object | null

object
notesoptionalstring | null

Free-text instructions for Blooio staff, e.g. eSIM details, a number to port in, or the country you need. Optional.

null
auto_bindoptionalstring

api_key_id of an API key in your organization that should own every line in this purchase. Each line is assigned to the key as soon as it gets its number, including lines Blooio staff provision later (custom requests, ZIP codes, out-of-stock area codes), so sends authenticated with that key can use them without a separate assignment call. A key deprecated before its line is provisioned is not assigned. Unknown keys return 404 auto_bind_api_key_not_found. Plans without number pools (shared_nc, shared_com, dedicated_com) let a key own one line, so on those plans auto_bind requires quantity: 1 and a key holding no other line on such a plan (else 409 auto_bind_exceeds_plan).

Returns

dataoptionalobject
purchase_idoptionalstring
statusoptionalstring
"provisioning""action_required"
action_urloptionalstring | null

Present when status is action_required: complete card authentication here.

Response codes

202Purchase accepted; provisioning proceeds asynchronously.
400Invalid request. `code` includes `invalid_plan`, `line_limit_exceeded`, `invalid_custom_requests` (`custom_requests` isn't an array of objects or nulls), `custom_requests_exceed_quantity` (more entries than `quantity`), and `custom_requests_not_supported` (a custom request on a shared plan).
401Your API key is missing or invalid. Pass it as a bearer token.
402Payment required or failed. `code` is `no_payment_method` (no saved card, and the credit doesn't cover the purchase) or `payment_failed` (the card was declined).
403Your API key isn't allowed to access this channel (blocked key or plan limit).
409Conflicts with a purchase rule, e.g. `shared_number_limit`.

Sends a live request with your values and shows the real response below. Your key is stored only in this browser.

Request
curl -X POST https://api.blooio.com/v4/channels/blooio/purchases \
Body object
Response objectexample
{  "data": {    "purchase_id": "idem_abc123",    "status": "provisioning"  }}