Skip to content

Place a phone number order

Submit a phone number order. Must be called as multipart/form-data because KYC document files are part of the request. Call POST /numbers/orders/check first to obtain the address-specific kycRequirements.

You may attach your own custom_order_reference (any short string, max 64 chars) - it will be echoed back to you in the response, in GET /numbers/orders/{id}, and in the asynchronous webhook payload below. If you omit it, the upstream provider will generate one and we'll backfill it on your row. order_id is the deprecated name for the same field: it is still accepted, but sending both order_id and custom_order_reference with different values is rejected (422) - identical values are fine.

The response also carries order_reference, the carrier's own identifier for the order (a UUID); use it to identify the order with the carrier (e.g. their support, or their KYC-document endpoint).

Order fulfilment is asynchronous. This endpoint returns 201 as soon as the order is accepted upstream. The final outcome (success or rejection) will be delivered to your webhook URL (if provided) and is queryable via GET /numbers/orders/{id}.

Webhook payload

When the order reaches its final state we POST to your webhook URL the exact same body as GET /numbers/orders/{id} (the schema below). Read the status field to tell success from rejection:

  • status: "success" - numbers and phone_numbers are populated.
  • status: "error" - error_message carries the rejection reason.
HTTP: IntegrationApiKey

API key created on the Cockpit Integrations page (an "API key" integration). It is a bearer token owned by the customer's PBX and limited to the scopes selected when the key was created (e.g. phone-numbers, push-configuration).

Send it in the Authorization header:

Authorization: Bearer <api_key>

Manage keys (create / reveal / revoke) from Integrations → New integration → API key.

HTTP Authorization Scheme
bearer

Request body · required · multipart/form-data

Request schema
customer_name*string
Legal name of the customer the numbers are ordered for. Required; forwarded to the carrier, which records and may validate it.
length: 0–255
example: ACME GmbH
street*string
example: Adenauerallee
street_number*string
example: 1
postal_code*string
example: 53113
city*string
example: Bonn
area_codestring | null
Country-conditional. Required for some countries (e.g. Switzerland, `CH`, where it would be something like `43`) and rejected (422) for others - it is `null` for the `DE` example here. Use the same value you sent to `POST /numbers/orders/check`.
length: 0–16
country*string
example: DE
quantity*integer
≥ 1
example: 1
webhookstring | null · uri
Optional URL we POST to once the order is fulfilled. The order is accepted asynchronously (this endpoint returns `201` with status `requested`), so the assigned numbers - or a rejection - are delivered here later, not in this response. See "Webhook payloads" above for the exact body. The same outcome can also be fetched from `GET /numbers/orders/{id}`.
length: 0–500
example: https://your-app.example/hooks/number-order
order_idstring | null
Deprecated - use `custom_order_reference` instead (same meaning, new name). Still accepted for backward compatibility. Sending both `order_id` and `custom_order_reference` with *different* values is rejected (422); sending both with the same value is fine.
length: 0–64deprecated
example: po-2026-00042
custom_order_referencestring | null
Optional customer reference (any short string, max 64 chars), opaque to us and to the carrier. Echoed back in the response, in `GET /numbers/orders/{id}`, and at the top level of the asynchronous webhook payload as `order_id` (the webhook body is the same order object). If omitted (and `order_id` is not sent either), the upstream provider generates one and we backfill it on your row.
length: 0–64
example: po-2026-00042
kycobject
KYC documents, one entry per `documentType` returned by `POST /numbers/orders/check` for the country. Send file documents as a file part `kyc[<documentType>]` and identifier-only documents as a form field `kyc[<documentType>]=<value>`. Accepted file MIME types: `application/pdf`, `image/jpeg`, `image/png`. Example shape: * `kyc[utility_bill]` - file part carrying `bill.pdf` * `kyc[id_document]` - file part carrying `passport.jpg` * `kyc[business_registration_number]=BE-12345` - form field For an OR group returned by the check endpoint (an array of types), provide any one of the listed `documentType`s.
Free-form object

Responses

Order accepted upstream and persisted on our side.
Response schema
idstring · uuid
Internal order id assigned by us. Use this with `GET /numbers/orders/{id}` to fetch the latest state. NOT the value echoed in the asynchronous webhook payload - that one is `order_id` (your own reference).
example: 550e8400-e29b-41d4-a716-446655440000
order_idstring | null
Your customer reference, supplied via the deprecated `order_id` field (or its replacement, `custom_order_reference`) in `POST /numbers/orders` (or `POST /numbers/orders/{id}`). Echoed back here, in `GET /numbers/orders/{id}`, and at the top level of the asynchronous webhook payload (which is this same object) as `order_id`. Kept for backward compatibility; new integrations should read `order_reference` to identify the order with the carrier, and may keep sending either `order_id` or `custom_order_reference` to set this value.
length: 0–64deprecated
example: po-2026-00042
order_referencestring | null · uuid
The carrier's own identifier for this order (a UUID they assign). Null until the order is placed. This is the reference the carrier says to use to identify the order, and it is distinct from `order_id` (your own reference, opaque to the carrier). Not settable by you.
example: 01a0ae76-0000-4000-8000-000000000000
customer_namestring
Legal name of the customer the numbers were ordered for, as supplied on create (and editable on retry).
example: ACME GmbH
statusstring
Lifecycle state of this order. * `requested`: sent upstream, awaiting fulfilment. * `submission_failed`: rejected during synchronous submission; editable + retryable. * `processing`: async success callback received; provisioning in progress. * `success`: provisioning complete; `numbers` is populated. * `error`: async rejection; terminal. * `processing_failed`: internal processing exhausted retries; admin-only retry.
enum: created requested submission_failed processing success error processing_failed
example: requested
addressobject
streetstring
example: Adenauerallee
street_numberstring
example: 1
postal_codestring
example: 53113
citystring
example: Bonn
area_codestring | null
Country-conditional (e.g. set for CH); null otherwise.
countrystring
example: DE
formatted_addressstring | null
Single-line, comma-separated address derived from the persisted components (street + number, postal code + city, country). Empty components are dropped.
example: Adenauerallee 1, 53113 Bonn, DE
quantityinteger
example: 1
prefixstring | null
Dial prefix in E.164 (country + area code if applicable).
example: +49228
numbersarray<string>
E.164-formatted numbers assigned to this order. Empty (`[]`) until the order reaches `success` - they are never returned synchronously by `POST /numbers/orders` (which only ever returns `requested`); they arrive later via the webhook and then appear here on `GET /numbers/orders/{id}`.
[]string
phone_numbersarray<object>
The assigned numbers, in the same shape as `GET /numbers` (id, number, name, is_active, call_flow), so you can read each number's id and current call flow and act on it directly (e.g. `PUT /numbers/{id}/call-flow`). Populated once the order reaches `success`.
idstring · uuid
example: 550e8400-e29b-41d4-a716-446655440000
numberstring
Phone number in E.164 format.
example: +12125550100
namestring | null
example: Customer Support
is_activeboolean
example: 1
call_flow_idstring | null · uuid
example: 550e8400-e29b-41d4-a716-446655440100
call_flowobject | null
idstring · uuid
namestring
enabledboolean
error_messagestring | null
Short error reason when status is `error` or `submission_failed`.
webhook_urlstring | null
The webhook URL we will POST the final outcome to.
webhook_statusstring
enum: not_required pending retrying delivered failed cancelled
webhook_next_retry_atstring | null · date-time
created_atstring · date-time
updated_atstring · date-time
Authorization Token Missing. This error is returned when the authorization token is missing.
Response schema
errorstring
Error message
example: Authorization Token is missing
Validation failed. `errors` maps each rejected field to its messages. If the order reached the carrier and was rejected there, it is persisted as a retryable `submission_failed` order and returned in `data` (the full order, same shape as `GET /numbers/orders/{id}`); use `data.id` to edit + retry it via `POST /numbers/orders/{id}`. When `data` is absent, no order was created.
Response schema
message*string
errors*object
Free-form object
dataobject
Present only for a carrier rejection (a retryable order was persisted). The full order - same shape as `GET /numbers/orders/{id}` - whose `id` you pass to `POST /numbers/orders/{id}` to edit + retry. Absent for local validation errors.
post https://cockpit.voxbi.com/api/v1/numbers/orders
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/numbers/orders' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -F 'customer_name=ACME GmbH' \
  -F 'street=Adenauerallee' \
  -F 'street_number=1' \
  -F 'postal_code=53113' \
  -F 'city=Bonn' \
  -F 'area_code=string' \
  -F 'country=DE' \
  -F 'quantity=1' \
  -F 'webhook=https://your-app.example/hooks/number-order' \
  -F 'order_id=po-2026-00042' \
  -F 'custom_order_reference=po-2026-00042'
const body = new FormData();
body.append('customer_name', 'ACME GmbH');
body.append('street', 'Adenauerallee');
body.append('street_number', '1');
body.append('postal_code', '53113');
body.append('city', 'Bonn');
body.append('area_code', 'string');
body.append('country', 'DE');
body.append('quantity', '1');
body.append('webhook', 'https://your-app.example/hooks/number-order');
body.append('order_id', 'po-2026-00042');
body.append('custom_order_reference', 'po-2026-00042');

const response = await fetch('https://cockpit.voxbi.com/api/v1/numbers/orders', {
  method: 'POST',
  headers: { Authorization: `Bearer ${YOUR_TOKEN}` },
  body,
});

const data = await response.json();
console.log(data);
import requests

response = requests.post(
    'https://cockpit.voxbi.com/api/v1/numbers/orders',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'},
    data={
        'customer_name': 'ACME GmbH',
        'street': 'Adenauerallee',
        'street_number': '1',
        'postal_code': '53113',
        'city': 'Bonn',
        'area_code': 'string',
        'country': 'DE',
        'quantity': '1',
        'webhook': 'https://your-app.example/hooks/number-order',
        'order_id': 'po-2026-00042',
        'custom_order_reference': 'po-2026-00042',
    },
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$ch = curl_init('https://cockpit.voxbi.com/api/v1/numbers/orders');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_TOKEN']);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'customer_name' => 'ACME GmbH',
    'street' => 'Adenauerallee',
    'street_number' => '1',
    'postal_code' => '53113',
    'city' => 'Bonn',
    'area_code' => 'string',
    'country' => 'DE',
    'quantity' => '1',
    'webhook' => 'https://your-app.example/hooks/number-order',
    'order_id' => 'po-2026-00042',
    'custom_order_reference' => 'po-2026-00042',
]);

$data = json_decode(curl_exec($ch), true);
print_r($data);
Sample request · multipart/form-data
{ … }
"customer_name": "ACME GmbH",
"street": "Adenauerallee",
"street_number": "1",
"postal_code": "53113",
"city": "Bonn",
"area_code": "string",
"country": "DE",
"quantity": "1",
"webhook": "https://your-app.example/hooks/number-order",
"order_id": "po-2026-00042",
"custom_order_reference": "po-2026-00042"
}
{ … }
"id": "550e8400-e29b-41d4-a716-446655440000",
"order_id": "po-2026-00042",
"order_reference": "01a0ae76-0000-4000-8000-000000000000",
"customer_name": "ACME GmbH",
"status": "requested",
"address": { … },
"street": "Adenauerallee",
"street_number": "1",
"postal_code": "53113",
"city": "Bonn",
"area_code": null,
"country": "DE"
},
"formatted_address": "Adenauerallee 1, 53113 Bonn, DE",
"quantity": 1,
"prefix": "+49228",
"numbers": [],
"phone_numbers": [],
"error_message": null,
"webhook_url": "https://your-app.example/hooks/number-order",
"webhook_status": "pending",
"webhook_next_retry_at": null,
"created_at": "2026-05-12T10:36:47+00:00",
"updated_at": "2026-05-12T10:36:47+00:00"
}
{ … }
"error": "Authorization Token is missing"
}
Cache-Control string
example: private, must-revalidate
Connection string
example: keep-alive
Content-Type string
example: application/json
Vary string
example: Origin
X-RateLimit-Limit integer
Max requests allowed in the current rate-limit window.
example: 60
X-RateLimit-Remaining integer
Requests remaining in the current rate-limit window.
example: 57
{ … }
"message": "The customer name field is required. (and 9 more errors)",
"errors": { … }
"customer_name": [ … ],
"The customer name field is required."
],
"street": [ … ],
"The street field is required."
],
"street_number": [ … ],
"The street number field is required."
],
"postal_code": [ … ],
"The postal code field is required."
],
"city": [ … ],
"The city field is required."
],
"country": [ … ],
"The country field is required."
],
"area_code": [ … ],
"The area code field is required."
],
"quantity": [ … ],
"The quantity field must be at least 1."
],
"webhook": [ … ],
"The webhook field must be a valid URL."
],
"order_id": [ … ]
"The order id field must not be greater than 64 characters."
]
}
}