Port-in orders
A port-in order transfers numbers from their current carrier onto the platform. Orders are asynchronous: after submission, progress depends on the losing carrier and can take from hours (US FastPort-style) to weeks (international/local processes).
Lifecycle
draft ──submit──▶ submitted ──▶ in_process ──▶ foc_scheduled ──▶ activating ──▶ completed
│ │ completed_partial
└── exception ◀─┘ fix requirements, resubmit ──▶ submitted
| Status | Meaning |
|---|---|
draft |
Created; fulfill requirements and end-user info, then submit |
submitted |
Sent to the provider; being validated |
in_process |
The losing carrier is processing the port |
exception |
Something was rejected — check requirements and comments, fix, resubmit |
foc_scheduled |
The port date (FOC — Firm Order Commitment) is confirmed; see foc_actual |
activating |
Numbers are being activated on the platform |
completed / completed_partial |
Done — numbers are live (partial: some numbers failed) |
cancel_pending |
Cancellation requested, awaiting provider confirmation |
cancelled / rejected |
Terminal |
Every transition emits a porting_order.status_changed webhook.
Order splitting
One POST /v2/porting_orders may return several orders. Numbers are
grouped by country and number type, and providers may split further (e.g. by
losing carrier). All orders from one request share a batch_id, and a
porting_order.split event tells you it happened. Each order is fulfilled
and submitted independently — always iterate over the response array.
Requirements
Each order carries requirements — the documents and data legally required
for its country, number type, and provider. Check them before ordering:
curl "https://api.example.com/v2/porting/requirements?country_code=GB&number_type=mobile" \
-H "Authorization: Bearer pk_live_YOUR_KEY"
Requirement statuses: requirement-info-pending → you must act;
requirement-info-under-review → we are validating;
requirement-info-exception → rejected, see exception_reason, resubmit;
approved → done.
To fulfill a textual requirement, PATCH the value; for a document requirement, upload the file first and pass its id:
# upload
curl -X POST https://api.example.com/v2/documents \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-F "file=@invoice.pdf" -F "document_date=2026-08-01T00:00:00Z"
# attach
curl -X PATCH https://api.example.com/v2/porting_orders/{order_id}/requirements/{req_id} \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"field_value": "DOCUMENT_ID"}'
Invoices and LOAs must usually be fresher than 30 days — we validate this at submit time so you fail fast instead of waiting days for a carrier rejection.
The LOA (Letter of Authorization)
Do not write your own LOA. Download the pre-filled one — it already contains the numbers, account holder, and service address from your order, which eliminates the typos that cause most rejections:
curl https://api.example.com/v2/porting_orders/{order_id}/loa \
-H "Authorization: Bearer pk_live_YOUR_KEY" -o loa.pdf
Have the account holder sign it, upload the signed PDF via POST /v2/documents,
and attach it to the loa requirement.
End-user data
end_user must match the losing carrier's records exactly — mismatches are
the second most common rejection cause. Provide entity_name (businesses) or
auth_person_name (individuals), the account_number at the losing carrier,
and the service location.
Exceptions
If the order hits exception:
GET /v2/porting_orders/{id}/requirements— look forrequirement-info-exceptionand itsexception_reason.GET /v2/porting_orders/{id}/comments— our operations team and the provider leave details here. You can reply viaPOST …/comments.- Fix the data or documents, then
POST …/submitagain.
Cancellation
POST /v2/porting_orders/{id}/cancel. A draft cancels instantly. After
submission the order enters cancel_pending — cancellation is not
guaranteed once the losing carrier has confirmed the port; watch for the
final cancelled (or a return to in_process) via webhook.
Duplicates and idempotency
- A number that is already active or in an active port on the platform is
refused with
409and the existing order ids. - Send
Idempotency-Keyon creation: retries with the same key and body return the original response instead of creating duplicate orders.