Skip to main content

Stand Alone Non-NANP Port-Ins (BETA)

Bandwidth supports Stand Alone Non-NANP Port-Ins for numbers in the United Kingdom. This article will cover the process for submitting a Stand Alone Non-NANP Port-In request.

Overview

The /portins API is used to create and manage a single port-in order for a set of telephone numbers that are portable and can be ported together.

In general, numbers can be ported togehter if they meet the following criteria:

  • They are located in the same country
  • They are hosted by the same losing carrier
  • They are all the same type of number (geographic, national, mobile, etc.)

High Level Steps

To create and manage a port-in, these are the basic steps:

  1. Create an address for the port-in. This is the address of the end-user or business.
  2. Find your losing carrier by referring to the using the losing carriers API.
  3. Find your porting document requirements by referring to the porting document requirements API.
  4. Create the port-in order, possibly in DRAFT state.
  5. Upload one or more porting documents.
  6. Submit the port-in order.
  7. Monitor the port-in order status.
  8. Optionally add notes to the order to communicate with Bandwidth.

These steps are not necessarily in a fixed order.

The remainder of this document provides more detailed information for creating and managing port-ins.

Creating an Address

The first step in creating a port-in is to create an address. This is the address of the end-user or business. The address is used to validate the port-in order and to provide the address to the losing carrier. In the past, the address was supplied with the port-in order, but for non-NANP port-ins, the address is now a separate resource managed by /api/v2/accounts/{accountId}/addresses.

Once the address is created, note the addressId returned in the response. This will be used when creating the port-in order.

Keep in mind, you can reuse an already created address.

Planning Your Port-In

Prior to creating a port-in order, you'll need to know the number type and country of the numbers being ported. You'll need to know the losing carrier of the numbers being ported. Finally, you should be familiar with the porting document requirements, which is based on country and number type.

Bandwidth provides two API tools to provide this information, once you know the country and number type:

You may submit up to 500 telephone numbers in a stand-alone non-NANP port-in. The numbers must belong to the same country, losing carrier, and have the same number type.

If you just want the earliest possible FOC date, you may omit the RequestedFocDate from the /accounts/\{accountId\}/portins payload.

Creating a Draft Port-in

Bandwidth provides the ability for you to create a port-in order in DRAFT state. This allows you to manipulate the order with minimal validation checking prior to submitting the port-in. In DRAFT state, a port-in order can exist without all of the mandatory elements, while you gather the necessary information from your customer or back-office systems. Then, when you are ready, you can submit the port-in and all of the validations will be run to ensure that the port-in can be successfully sent to our porting vendor for processing.

To create a DRAFT port-in, you must include the ProcessingStatus element with a value of “draft” when you create the port-in using POST /accounts/{accountId}/portins.

Then you can use PUT /accounts/{accountId}/portins/{orderId} to add or change your port-in order.

When you are ready to submit the draft port-in order, simply PUT to the order with the ProcessingStatus value changed to “submitted”.

Be aware that draft port-in orders are automatically removed from the system if they remain in the draft state and sit idle (i.e. no PUT updates) for 48 hours since the last update.

Creating a Regular Port-in

Use POST /accounts/{accountId}/portins to create a port-in order for regular (non toll free) telephone numbers. This API is asynchronous, meaning the POST will create an order with a unique order-id that you will use to check status as it progresses. Please see Order Model for more information.

When you POST to /accounts/{accountId}/portins, some validation is performed to ensure that your request is properly formed. If errors are detected during this validation, you will receive a 4xx response that includes one or more Errors objects, containing an error code and description. These errors must be corrected before resubmitting the POST operation.

If your request passes the initial round of validation, you will receive a 201 response, including an OrderId element with a unique string that you will use to refer to the port-in order in subsequent requests. Additional validation is performed at this point, and if errors are detected, the 201 response will include one or more Errors objects and the ProcessingStatus will be set to Exception. In this case, the order is created and you must use PUT /accounts/{accountId}/portins/{orderId} to correct the errors.

Port-in orders will activate update to 24 hours before the Actual FOC Date.

Fetching Port-in Status

Anytime you need an update on the status of a port-in order, you should use GET /accounts/{accountId}/portins/{orderId}. This will return the latest information about the port-in. You should do this even if you receive a notification about an order state change, because the GET response contains more information than the notification.

As we've mentioned in other places, port-in orders can take days to complete. While waiting for completion, you may poll the port-in order, or you may subscribe to port-in order status change and notes events.

The key items to look for in the 200 response to GET /accounts/{accountId}/portins/{orderId} are:

  • ProcessingStatus - this is the current port-in order state. The values may be:
    • DRAFT - The regular port-in order is in draft state and has not been submitted
    • MISSING_REQUIREMENTS - The port-in order requires one or more porting documents to be uploaded before it can be submitted.
    • SUBMITTED - The port-in order has been submitted to the porting vendor.
    • EXCEPTION - The port-in order has a problem that requires intervention. The order will include error information describing the problem.
    • REQUESTED_SUPP - A request to update the order has been submitted.
    • FOC - A firm order commitment date has been agreed upon. The date appears in the order as ActualFocDate.
    • REQUESTED_CANCEL - A request to cancel the order has been submitted.
    • CANCELLED - The order is cancelled. This could be because someone cancelled it (no errors will be present), or because the order incurred an error that could not be corrected.
    • COMPLETE - The order is complete.
  • The presence of Errors objects.

Updating a Port-in

A port-in order can be updated using PUT /accounts/{accountId}/portins/{orderId}. The rules about what can be changed vary depending on whether the order is in a draft state, and the port type.

When a port-in order is in one of the draft states (DRAFT or MISSING_REQUIREMENTS), all elements may be updated using the PUT operation.

After an order has been submitted, the fields you are allowed to change vary depending on the port-type.

  • SiteId
  • SippeerId
  • LosingCarrierName
  • RequestedFocDate
  • CustomerOrderId
  • SubscriberType
  • AddressId
  • FirstName
  • LastName
  • BusinessName
  • VatNumber

If a port-in order already has a FOC date assigned, there are limits on how near to the FOC date and activation time you may update the port-in order. Generally, you cannot update a port-in if the FOC date and activation time are less than 24 hours in the future.

Adding Documents to a Port-in

Any time a port-in is requested, one or more porting documents may be required by the carrier or account from which the telephone number is being ported. These can include a letter of authorization (LOA), copy of bill (COB), or an invoice.

Porting documents must be uploaded prior to submission of the port-in. The port-in will remain in the MISSING_REQUIREMENTS state until all required documents have been uploaded.

Document sizes are restricted to 20 mega-bytes.

Once a porting document is uploaded, it has the status "Pending Validation". The document will be reviewed by Bandwidth and the status will be updated to "Valid" or "Invalid". If the document is invalid, the reason will be included in the order notes

Documents and metadata are uploaded using POST /api/v2/accounts/{accountId}/porting/portinOrders/{orderId}/documents API. The port-in order must be created prior to uploading documents. The 201 response will assign a unique file identifier that is used to delete, update, or attach metadata to the document.

Documents may be removed from a port-in order using DELETE /api/v2/accounts/{accountId}/porting/portinOrders/{orderId}/documents/{documentId}. Documents can only be removed if the order is in the DRAFT state.

Documents and metadata may be replaced using PUT /api/v2/accounts/{accountId}/porting/portinOrders/{orderId}/documents/{documentId}. Documents can only be replaced if the order in the DRAFT state or the document is INVALID.

See the list of porting documents you have uploaded for a port-in order using GET /api/v2/accounts/{accountId}/porting/portinOrders/{orderId}/documents.

Supported Formats

Bandwidth supports document uploads in the following formats.

Document TypeContent Header
JPG/JPEGimage/jpeg
PDFapplication/pdf
XLSapplication/vnd.ms-excel
XLSXapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Port-in Order Notes

The port-in notes capability provides a means to communicate with Bandwidth regarding a specific port-in order. When you add a note to a port-in order, a Zendesk ticket is automatically created and sent to our LNP team. The LNP team can also use notes to communicate back to you. If you are subscribed to port-in order status notifications, you will also be notified if Bandwidth adds a note to your order.

This capability is very useful for the following type of exchange:

You: Hey, I submitted this order 3 days ago and I have not received FOC.  Can you tell me what's going on?

This creates a Zendesk ticket that will be assigned to someone on our LNP team to address.

Bandwidth: I've checked with the porting vendor and they are having difficulty getting a response from the losing carrier.  I'll continue to follow up.

This will show up in the order history on the Bandwidth Dashboard’s Port-in Order Details page. And, if you are subscribed to port-in order status notifications, will notify you via email or webhook, depending on your notification preferences.

Order notes increase productivity by making it easy to ask about an order without you having to cut and paste all of the order context information (e.g. order-id or PON, order state, what you’ve tried, etc.) into a separate ticketing system.

A note may be created using POST /accounts/{accountId}/portins/{orderId}/notes. The 201 response will assign a unique note identifier allowing you to update the note, if necessary.

You may fetch all of the notes for a port-in order using GET /accounts/{accountId}/portins/{orderId}/notes.

You can update an existing order note using PUT /accounts/{accountId}/portins/{orderId}/notes/{noteId}.

Port-in Order History

Each time a port-in order is created or changes state, a history entry is created showing the order status, a note indicating what happened, the date and time of the change, and what was changed if the order was modified. This order history is retained by Bandwidth as a history of the port-in order.

You can fetch the port-in order history using GET /accounts/{accountId}/portins/{orderId}/history.

Note that it occasionally takes a minute or two to update the order history. So if you perform an operation and immediately fetch the order history, the operation may not yet be reflected.

Finding a Port-in Order

Bandwidth’s GET /accounts/{accountId}/portins API provides a way to search for port-in orders using a number of filters. This can be useful if you do not have the port-in order-id for an order, or if you need to find out if a port-in was created for a particular telephone number, etc.

Because this API has the potential to match a large number of port-in orders, the results are paginated. The pagination is controlled by two mandatory query parameters called page and size. Generally you start by setting page to 1, and size to the number of entries you want per page.

If more results exist than the number specified by “size”, you will have to fetch the next page. This can be done by using the Links element in the response payload.

The following query parameters can be used to filter the results. They are all logically ANDed together, such that the results will match all of the query parameters that are present in your query.

  • status - only orders in the specified state
  • startdate - the earliest last-modified date to include
  • enddate - the latest last-modified date to include
  • orderTn - one of the TNs being ported
  • customerOrderId - orders matching this customer order id
  • pon - orders having this PON
  • date - only orders modified on this date

These query parameters are defined in the API reference.

The response will include the pagination links mentioned above, plus a TotalCount element indicating how many results there are in total, which might be greater than the value you supplied for “size”. The results will also contain an object for each order that matched all of your query parameters (limited to “size” entries). This object differs slightly from the data you would receive if you queried the specific order-id using GET /accounts/{accountId}/portins/{orderId}, but includes the main port-in fields, including the order-id.

Cancelling a Port-in

You may cancel a stand-alone port-in using DELETE /accounts/{accountId}/portins/{orderId}.

If the port-in order is in DRAFT state, cancelling the order will remove it from the system entirely.

If the port-in order has already been submitted, the port-in order will transition to the REQUESTED_CANCEL.

If a port-in order already has a FOC date assigned, there are limits on how near to the FOC date and activation time you may cancel the port-in order. Generally, you cannot cancel a port-in if the FOC date and activation time are less than 24 hours in the future.

The CANCELLED state is a terminal state, so you cannot do anything further with the order once it has reached this state.

If you've submitted an order that should not, or cannot complete, it is important that you cancel the order so that the telephone numbers in the order will not be prevented from appearing in subsequent orders.

Example

Let's walk through an example of creating a port-in order for a single telephone number. I will be porting a UK number, +442012345555 from BT to Bandwidth.

Let's start by creating an address for the port-in.

Our request:

POST /api/v2/accounts/1234567/addresses
Host: dashboard.bandwidth.com
Authorization: {Authorization}
Content-Type: application/json

{
"addressLine1": "221 Brooklyn Square",
"city": "Nottingham",
"countryCodeA3": "GBR",
"customReference": "home_office",
"isHidden": false,
"postalCode": "WC1B 3JA"
}

The response:


"links": [
{
"href": "https://dashboard.bandwidth.com/api/v2/accounts/1234567/addresses/4b860f0d-efe8-4f0a-9472-3d276c221c93",
"rel": "get-address",
"method": "GET"
}
],
"data": {
"address": {
"city": "Nottingham",
"postalCode": "WC1B 3JA",
"createdDateTime": "2024-01-29T15:33:14.335191654Z",
"addressId": "4b860f0d-efe8-4f0a-9472-3d276c221c93",
"updatedDateTime": "2024-01-29T15:33:14.335191654Z",
"customReference": "home_office",
"countryCodeA3": "GBR",
"addressLine1": "221 Brooklyn Square",
"isHidden": false
}
},
"errors": []
}

Make note of the addressId in the response. We will use this when we create the port-in order.

We are porting a Geographic number in the UK. We can use this information to look identify the losing carrier and the porting document requirements.

We should already know the losing carrier, but we should verify that we can find it in using the losing carriers API, querying by country and number type.

Our request:

GET /api/v2/porting/losingCarriers?countryCodeA3=GBR&phoneNumberType=GEOGRAPHIC
Host: dashboard.bandwidth.com
Authorization: {Authorization}

The response:

{
"links": [
{
"href": "/porting/losingCarriers",
"rel": "self",
"method": "GET"
}
],
"data": [
{
"name": "Affinity"
},
{
"name": "BT"
},
{
"name": "Gamma"
}
]
}

BT is a valid losing carrier for our port-in.

Next, we need to know the porting document requirements for the port-in. We can use the porting document requirements API to find this information.

Our request:

GET /api/v2/porting/referenceDocuments?countryCodeA3=GBR&phoneNumberType=GEOGRAPHIC
Host: dashboard.bandwidth.com
Authorization: {Authorization}

Response

{
"links": [
{
"href": "/porting/referenceDocuments",
"rel": "self",
"method": "GET"
}
],
"data": {
"referenceDocuments": [
{
"countryCodeA3": "GBR",
"phoneNumberType": "GEOGRAPHIC",
"residential": [
{
"type": "LOA",
"description": "LOA description",
"requiredDocument": true,
"supportedFileTypes": [
"pdf",
"xls",
"xlsx",
"jpg",
"jpeg"
]
},
{
"type": "COB",
"description": "Copy of bill",
"requiredDocument": true,
"supportedFileTypes": [
"pdf",
"xls",
"xlsx",
"jpg",
"jpeg"
]
}
]
}
]
}
}

For this port, we need to upload a letter of authorization (LOA) and a copy of the bill (COB). Our end user type is residential.

Now we can create the port-in order. We will create the order in DRAFT state, so that we can add the porting documents before submitting the order.

Our request

POST /api/v2/accounts/1234567/portins
Content-Type: application/xml
Authorization: {Authorization}

<LnpOrder>
<SiteId>100</SiteId>
<PeerId>3000</PeerId>
<LosingCarrierName>BT</LosingCarrierName>
<ListOfPhoneNumbers>
<PhoneNumber>+442012345555</PhoneNumber>
</ListOfPhoneNumbers>
<CustomerOrderId>custom-order-id</CustomerOrderId>
<RequestedFocDate>2024-01-31</RequestedFocDate>
<Subscriber>
<SubscriberType>RESIDENTIAL</SubscriberType>
<FirstName>Jody</FirstName>
<LastName>Smith</LastName>
<AddressId>4b860f0d-efe8-4f0a-9472-3d276c221c93</AddressId>
</Subscriber>
</LnpOrder>

The response:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LnpOrderResponse>
<OrderId>9c84fcec-79f2-4a80-9784-3d4cd75b820d</OrderId>
<Status>
<Code>201</Code>
<Description>Order request received. Please use the order id to check the status of your order later.
</Description>
</Status>
<ProcessingStatus>DRAFT</ProcessingStatus>
<RequestedFocDate>2024-01-31</RequestedFocDate>
<Subscriber>
<SubscriberType>RESIDENTIAL</SubscriberType>
<FirstName>Jody</FirstName>
<LastName>Smith</LastName>
<AddressId>4b860f0d-efe8-4f0a-9472-3d276c221c93</AddressId>
</Subscriber>
<ListOfPhoneNumbers>
<PhoneNumber>+442012345555</PhoneNumber>
</ListOfPhoneNumbers>
<SiteId>100</SiteId>
<PeerId>3000</PeerId>
<LosingCarrierName>BT</LosingCarrierName>
<CustomerOrderId>custom-order-id</CustomerOrderId>
<PartialPort>false</PartialPort>
</LnpOrderResponse>

Note the OrderId in the response. We will use this to add the porting documents and submit the order.

Now we can upload the porting documents. First, we'll upload the LOA.

Our request:

POST /api/v2/accounts/1234567/porting/portinOrders/9c84fcec-79f2-4a80-9784-3d4cd75b820d/documents
Host: dashboard.bandwidth.com
Authorization: {Authorization}
Content-Type: multipart/form-data; boundary=boundary

--boundary
Content-Disposition: form-data; name="file"; filename="loa.pdf"
Content-Type: application/pdf

<LOA PDF>

--boundary
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

{
"contentType": "application/pdf",
"type": "LOA",
"customReference": "loa-001"
}
------Boundary7MA4YWxkTrZu0gW

The response:

{
"data": {
"id": "6c4cb5e2-b6dc-4730-b644-e4e593ea2766",
"type": "LOA",
"customReference": "loa-001.pdf",
"status": "PENDING_VALIDATION",
"contentType": "application/pdf",
"createdDateTime": "2024-01-30T20:31:08.985Z",
"updatedDateTime": "2024-01-30T20:31:08.985Z"
},
"errors": [],
"links": [
{
"href": "https://dashboard.bandwidth.com/api/v2/accounts/9902989/porting/portinOrders/9c84fcec-79f2-4a80-9784-3d4cd75b820d/documents",
"rel": "self",
"method": "GET"
}
]
}

Next, we'll upload the COB.

Our request:

POST /api/v2/accounts/1234567/porting/portinOrders/9c84fcec-79f2-4a80-9784-3d4cd75b820d/documents
Host: dashboard.bandwidth.com
Authorization: {Authorization}
Content-Type: multipart/form-data; boundary=boundary

--boundary
Content-Disposition: form-data; name="documentContent"; filename="cob.pdf"
Content-Type: application/pdf

<COB PDF>

--boundary
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

{
"contentType": "application/pdf",
"type": "COB",
"customReference": "cob-001"
}
--boundary--

The response:

{
"data": {
"id": "f4467d98-1b70-4b3c-9f32-8d8a9d1ae061",
"type": "COB",
"customReference": "cob-001.pdf",
"status": "PENDING_VALIDATION",
"contentType": "application/pdf",
"createdDateTime": "2024-01-30T20:31:08.985Z",
"updatedDateTime": "2024-01-30T20:31:08.985Z"
},
"errors": [],
"links": [
{
"href": "https://dashboard.bandwidth.com/api/v2/accounts/9902989/porting/portinOrders/9c84fcec-79f2-4a80-9784-3d4cd75b820d/documents",
"rel": "self",
"method": "GET"
}
]
}

Now we can submit the port-in order.

Our request:

PUT /api/v2/accounts/1234567/portins/9c84fcec-79f2-4a80-9784-3d4cd75b820d
Host: dashboard.bandwidth.com
Authorization: {Authorization}
Content-Type: application/xml

<LnpOrder>
<ProcessingStatus>SUBMITTED</ProcessingStatus>
</LnpOrder>

The response:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LnpOrderResponse>
<OrderId>9c84fcec-79f2-4a80-9784-3d4cd75b820d</OrderId>
<Status>
<Code>200</Code>
<Description>Supp request received. Please use the order id to check the status of your order later.
</Description>
</Status>
<ProcessingStatus>REQUESTED_SUPP</ProcessingStatus>
</LnpOrderResponse>

Now we can check the status of the port-in order.

Our request:

GET /api/v2/accounts/1234567/portins/9c84fcec-79f2-4a80-9784-3d4cd75b820d
Host: dashboard.bandwidth.com
Authorization: {Authorization}

The response:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LnpOrderResponse>
<ProcessingStatus>SUBMITTED</ProcessingStatus>
<RequestedFocDate>2024-01-31T00:00:00Z</RequestedFocDate>
<EarliestEstimate>2024-01-31T00:00:00Z</EarliestEstimate>
<Subscriber>
<SubscriberType>RESIDENTIAL</SubscriberType>
<FirstName>Jody</FirstName>
<LastName>Smith</LastName>
<AddressId>4b860f0d-efe8-4f0a-9472-3d276c221c93</AddressId>
</Subscriber>
<ListOfPhoneNumbers>
<PhoneNumber>+442012345555</PhoneNumber>
</ListOfPhoneNumbers>
<PON>979E024026CB035C</PON>
<AccountId>1234567</AccountId>
<SiteId>100</SiteId>
<PeerId>3000</PeerId>
<LosingCarrierName>BT</LosingCarrierName>
<VendorName>International porting vendor</VendorName>
<OrderCreateDate>2024-01-26T00:39:51.456Z</OrderCreateDate>
<LastModifiedDate>2024-01-26T19:17:20.783Z</LastModifiedDate>
<userId>portingUser</userId>
<LastModifiedBy>portingUser</LastModifiedBy>
<CustomerOrderId>custom-order-id</CustomerOrderId>
<BillingType>PORTIN</BillingType>
<PortType>MANUAL</PortType>
<AutoActivation>true</AutoActivation>
<CountryCodeA3>GBR</CountryCodeA3>
<PhoneNumberType>GEOGRAPHIC</PhoneNumberType>
</LnpOrderResponse>

Our port-in has been submitted. It will be validated and move to the FOC state upon successful validation.