Porting
Bring an existing number over from another carrier
Porting
If you already own a number with another carrier, port it in instead of buying a new one. Porting supports US and Canadian numbers. The flow is: check portability, upload the two required documents, then submit the port-in. Ported numbers arrive voice-ready (and SMS-ready where the order supports messaging).
1. Check portability
Confirm the number can be moved before collecting anything from the customer. The check returns a results array, one entry per number, each with portable, fastPortable, messagingCapable, and a notPortableReason when it cannot be moved.
const { data } = await zernio.phonenumbers.checkPhoneNumberPortability({
body: { phoneNumbers: ['+14155551234'] }
});
data.results.forEach(r =>
console.log(r.phoneNumber, r.portable, r.fastPortable, r.notPortableReason)
);response = client.phone_numbers.check_phone_number_portability(
phone_numbers=['+14155551234']
)
for r in response.results:
print(r.phone_number, r.portable, r.fast_portable, r.not_portable_reason)curl -X POST "https://zernio.com/api/v1/phone-numbers/port-in/check" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumbers": ["+14155551234"]}'2. Upload the documents
A port-in needs a Letter of Authorization (LOA) and a recent invoice from the losing carrier proving ownership. Upload each with uploadPhoneNumberPortInDocument (POST /v1/phone-numbers/port-in/documents) as multipart form data: a file part (PDF, JPEG, or PNG, up to 10 MB) and a kind part (loa or invoice). Keep the returned documentId for the submit.
# Upload the LOA (returns { documentId })
curl -X POST "https://zernio.com/api/v1/phone-numbers/port-in/documents" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F file=@loa.pdf \
-F kind=loa
# Repeat for the invoice
curl -X POST "https://zernio.com/api/v1/phone-numbers/port-in/documents" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F file=@invoice.pdf \
-F kind=invoice3. Submit the port-in
Submit the numbers, the LOA and invoice documentIds, and the end-user account details in endUser. The transfer PIN goes in endUser.pinPasscode; it is forwarded to the carrier and never stored by Zernio. countryCode must be US or CA.
const { data } = await zernio.phonenumbers.createPhoneNumberPortIn({
body: {
phoneNumbers: ['+14155551234'],
loaDocumentId: 'DOC_LOA',
invoiceDocumentId: 'DOC_INVOICE',
endUser: {
entityName: 'Acme Ltd',
authPersonName: 'Jane Doe',
streetAddress: '10 Market St',
locality: 'San Francisco',
administrativeArea: 'CA',
postalCode: '94103',
countryCode: 'US',
pinPasscode: '1234', // transfer PIN, forwarded to the carrier, never stored
},
}
});
data.orders.forEach(o => console.log(o.id, o.status, o.error ?? 'ok'));curl -X POST "https://zernio.com/api/v1/phone-numbers/port-in" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumbers": ["+14155551234"],
"loaDocumentId": "DOC_LOA",
"invoiceDocumentId": "DOC_INVOICE",
"endUser": {
"entityName": "Acme Ltd",
"authPersonName": "Jane Doe",
"streetAddress": "10 Market St",
"locality": "San Francisco",
"administrativeArea": "CA",
"postalCode": "94103",
"countryCode": "US",
"pinPasscode": "1234"
}
}'The carrier may split your numbers into several orders (by country, number type, or losing carrier). The response orders[] carries per-order results. A partial failure still returns 201: the failed orders come back with their error set and stay as cancellable drafts, so you can fix and resubmit just those.
Track and cancel
List your in-flight port-ins with listPhoneNumberPortIns (GET /v1/phone-numbers/port-in), and cancel a draft or pending order with cancelPhoneNumberPortIn (DELETE /v1/phone-numbers/port-in/{id}). Once the losing carrier completes the transfer, the number appears in your regular number list, voice-ready.