Open SidemenuDocs
Docs
Close Sidemenu

Quickstartquickstart

Number Porting V2 (BETA)number-porting-v2--beta-

Workflow Steps:

  1. 1Check portability
  2. 2Initiate one or many porting orders
  3. 3Submit Supporting Documents or Use auto-generated LoA
  4. 4Complete all Porting Orders
  5. 5Confirm all infos
  6. 6Document Links
  7. 7Setup webhook URL for eligible port events
    • In Process → Submitted
    • Submitted → Exception
    • Submitted → FOC Date Confirmed
    • FOC Date Confirmed → Ported

Check portabilitycheck-portability

https://developers.telnyx.com/docs/api/v2/porting/Phone-Number-Porting#postPortabilityCheck

curl --location --request POST 'https://api.telnyx.com/v2/portability_checks' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "phone_numbers": [
        "+13125552486",
        "+12125558724"
    ]
}'

Response:

{
    "data": [
        {
            "fast_portable": true,
            "not_portable_reason": null,
            "phone_number": "+12125558724",
            "portable": true,
            "record_type": "portability_check_result"
        },
        {
            "fast_portable": true,
            "not_portable_reason": null,
            "phone_number": "+13125552486",
            "portable": true,
            "record_type": "portability_check_result"
        }
    ]
}

The user will get back a list of portable and nonportable numbers. Proceeding to Step 2 with nonportable numbers will result in 4xx errors.

Initiate one or many porting ordersinitiate-one-or-many-porting-orders

curl --location --request POST 'https://api.telnyx.com/v2/porting_orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
"phone_numbers": [
        "+16785554405"
    ]
}'

Depending on the count of Old Service Providers present, the user may get back a collection of one or many Porting Orders in draft state.

Submit Supporting Documentssubmit-supporting-documents

curl --location --request POST 'https://api.telnyx.com/v2/documents' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
}'

Or upload as multipart:

curl --location --request POST 'https://api.telnyx.com/v2/documents' \
--header 'Content-Type: multipart/form-data' \
--header 'Authorization: Bearer [REDACTED]' \
--form 'file=@/Users/xd/Downloads/threads-bugs.pdf'

Or upload as a base64 encoded file

curl --location --request POST 'https://api.telnyx.com/v2/documents' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "file": "{Base64 Encoded File}"
}'

Alternative

For users who would like to use the automatically generated Letter of Authorization (LoA) for signing, you can embed the generated LoA for your own signing.

curl --location --request GET 'https://api.telnyx.com/v2/porting_orders/a158957f-3a28-4348-ba62-f70d13f68dae/loa_template' \
--header 'Authorization: Bearer [REDACTED]'

Complete all Porting Orderscomplete-all-porting-orders

At this point, the user has all the necessary info to complete a Porting Order. Please note the webhook URL for callbacks on status change. More on this later.

The user has the option of updating each bit of info at a time. For example, in this example, all the info except documents field is updated first before it is updated.

Part 1

curl --location --request PATCH 'https://api.telnyx.com/v2/porting_orders/d25fed86-1f15-4f29-a0c0-ec923b18ee46' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "misc": {
        "type": "partial",
        "remaining_numbers_action": "keep",
        "new_billing_phone_number": "+13125557420"
    },
    "end_user": {
        "admin": {
            "entity_name": "Telnyx",
            "auth_person_name": "John Doe",
            "billing_phone_number": "+13129457420",
            "account_number": "1",
            "tax_identifier": "",
            "pin_passcode": "",
            "business_identifier": ""
        },
        "location": {
            "street_address": "311 W Superior St",
            "extended_address": "Suite 504",
            "locality": "Chicago",
            "administrative_area": "IL",
            "postal_code": "60654",
            "country_code": "US"
        }
    },
    "activation_settings": {
        "foc_datetime_requested": "2021-04-25T13:39:42Z"
    },
    "phone_number_configuration": {
        "connection_id": "",
        "message_profile_id": "",
        "emergency_address_id": "",
        "tags": [
            "culpa quis",
            "consectetur"
        ]
    },
    "user_feedback": {
        "user_rating": 60324306,
        "user_comment": "aliqua eu cillum ea"
    },
    "webhook_url": "https://example.com/9c4ac3ce-43d8-4a3f-bcdc-2831747c7105",
    "user_reference": "test"
}'

Part 2

curl --location --request PATCH 'https://api.telnyx.com/v2/porting_orders/d25fed86-1f15-4f29-a0c0-ec923b18ee46' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "documents": {
        "loa": "64ffb720-04c7-455b-92d6-20fcca92e935",
        "invoice": "ce74b771-d23d-4960-81ec-8741b3862146"
    }
}'

If the user desires to do this in two steps as shown above, the user must successfully PATCH with all info but the document field first before attempting to do so for documents only field.

Additionally, if any fields are invalid, PATCH will not be successful. In this example, the API responds with 422

curl --location --request PATCH 'https://api.telnyx.com/v2/porting_orders/e0fcd703-efec-48cb-b5ed-a6dbd56354e9' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer [REDACTED]' \
--data-raw '{
    "misc": {
        "type": "full",
        "remaining_numbers_action": "keep",
        "new_billing_phone_number": "+1 I am not valid"
    },
    "end_user": {
        "admin": {
            "entity_name": "Telnyx",
            "auth_person_name": "X.D. Zhai",
            "billing_phone_number": "+1 I am not valid",
            "account_number": "1",
            "tax_identifier": "",
            "pin_passcode": "",
            "business_identifier": ""
        },
        "location": {
            "street_address": "311 W Superior St",
            "extended_address": "Suite 504",
            "locality": "Chicago",
            "administrative_area": "IL",
            "postal_code": "60654",
            "country_code": "US"
        }
    },
    "activation_settings": {
        "foc_datetime_requested": "2020-11-06T13:39:42Z"
    },
    "phone_number_configuration": {
        "connection_id": "",
        "message_profile_id": "",
        "emergency_address_id": "",
        "tags": [
            "culpa quis",
            "consectetur"
        ]
    },
    "documents": {
        "loa": "64ffb720-04c7-455b-92d6-20fcca92e935",
        "invoice": "ce74b771-d23d-4960-81ec-8741b3862146"
    },
    "user_feedback": {
        "user_rating": "",
        "user_comment": ""
    },
    "webhook_url": "https://example.com/4f141040-3bab-410b-8cec-9551a8195882",
    "customer_reference": "1-alpha-2-bravo-3-charlie"
}'

Response:

{
    "errors": [
        {
            "detail": {
                "admin": {
                    "billing_phone_number": [
                        "is invalid"
                    ]
                }
            },
            "source": {
                "pointer": "/end_user"
            },
            "title": "Invalid end_user"
        },
        {
            "detail": {
                "new_billing_phone_number": [
                    "is invalid"
                ]
            },
            "source": {
                "pointer": "/misc"
            },
            "title": "Invalid misc"
        }
    ]
}

Confirm all infoconfirm-all-info

Confirm the porting order when you are satisfied with the information.

curl --location --request POST 'https://api.telnyx.com/v2/porting_orders/d25fed86-1f15-4f29-a0c0-ec923b18ee46/actions/confirm' \
--header 'Authorization: Bearer [REDACTED]'

A detour --- Documents have owners and you can see what particular resource owns the a document

curl --location --request GET 'https://api.telnyx.com/v2/document_links?page[number]=1&page[size]=20&filter[document_id]=65573c68-2913-42a1-b7d7-cba0385bdde0' \
--header 'Authorization: Bearer [REDACTED]'

Response:

{
    "data": [
        {
            "created_at": "2020-10-27T16:04:33Z",
            "document_id": "65573c68-2913-42a1-b7d7-cba0385bdde0",
            "id": "a7b42a18-b33b-43fc-8e50-362032854f4c",
            "linked_record_type": "porting_order",
            "linked_resource_id": "a158957f-3a28-4348-ba62-f70d13f68dae",
            "record_type": "document_link",
            "updated_at": "2021-03-27T16:04:33Z"
        }
    ],
    "meta": {
        "page_number": 1,
        "page_size": 20,
        "total_pages": 1,
        "total_results": 1
    }
}

You also have the options to filter documents by the owning resource ID

curl --location -g --request GET 'https://api.telnyx.com/v2/document_links?filter[linked_resource_id]=becb019f-af6a-48c1-980a-f0a856e84db7' \
--header 'Authorization: Bearer [REDACTED]'

Response:

{
    "data": [
        {
            "created_at": "2020-12-28T21:04:42Z",
            "document_id": "8c643671-62f8-4445-8e1e-5348b2165468",
            "id": "308da510-74d8-4a11-9ab4-ebddf5aa2e26",
            "linked_record_type": "porting_order",
            "linked_resource_id": "becb019f-af6a-48c1-980a-f0a856e84db7",
            "record_type": "document_link",
            "updated_at": "2021-03-28T21:04:42Z"
        },
        {
            "created_at": "2020-12-28T21:04:42Z",
            "document_id": "8c643671-62f8-4445-8e1e-5348b2165468",
            "id": "779b2570-0bc3-4ad3-beef-14a0f5a610cc",
            "linked_record_type": "porting_order",
            "linked_resource_id": "becb019f-af6a-48c1-980a-f0a856e84db7",
            "record_type": "document_link",
            "updated_at": "2021-03-28T21:04:42Z"
        }
    ],
    "meta": {
        "page_number": 1,
        "page_size": 20,
        "total_pages": 1,
        "total_results": 2
    }
}

Setup webhook URL for eligible port eventssetup-webhook-url-for-eligible-port-events

There are two types of events for a Porting Order:

  • Status change
  • Comments

You can set a webhook URL on a particular Porting Order. In the following section, examples of webhooks for each state transition are shown; the parameters in the payload to look out for are highlighted.

In Process → Submitted

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "12ae614e-ed37-4a19-9fe3-2b69bf33d429",
    "occurred_at": "2021-01-19T19:52:13.874635Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [],
        "value": "submitted"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-03-19T19:52:13+00:00",
      "webhook_url": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

Submitted → Exception

A Porting Order can have multiple underlying Exception reasons. When resolved, Porting Order re-enters Submitted state. The webhook will be the same as the previous section.

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "72322cb3-b6c6-46a4-a571-21a759c02da0",
    "occurred_at": "2021-01-19T19:51:37.844234Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [
          {
            "code": "ACCOUNT_NUMBER_MISMATCH",
            "description": "Account number does not match that on the CSR"
          },
          {
            "code": "PORTING_ORDER_SPLIT_REQUIRED",
            "description": "The OSP requires this Porting Order to be split map_exception_detail and submitted as separate orders"
          },
          {
            "code": "LOA_ILLEGIBLE",
            "description": "The LOA is illegible"
          }
        ],
        "value": "exception"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-03-19T19:51:37+00:00",
      "webhook_url": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

Submitted → FOC Date Confirmed

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "80227461-b684-4e89-a1a9-5055a2b4d8ef",
    "occurred_at": "2021-03-19T19:48:58.261079Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [],
        "value": "foc-date-confirmed"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-03-19T19:48:57+00:00",
      "webhook_url": "https://webhook.site/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://webhook.site/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

FOC Date Confirmed → Ported

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "334e12a2-a016-489e-a2b6-7abb46637327",
    "occurred_at": "2021-03-19T19:48:58.261079Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [],
        "value": "ported"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-03-19T19:48:57+00:00",
      "webhook_url": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

Misc: Retrieving phone numbers of a particular Porting Order

You can use the /phone_numbers endpoint to retrieve all Phone Numbers of a Porting Order.

curl --location --request GET 'https://api.telnyx.com/v2/porting_phone_numbers?page[number]=1&page[size]=20&filter[porting_order_id]=a158957f-3a28-4348-ba62-f70d13f68dae' \
--header 'Authorization: Bearer [REDACTED]'
{
    "data": [
        {
            "activation_status": null,
            "phone_number": "+13129457420",
            "portability_status": "confirmed",
            "porting_order_id": "a158957f-3a28-4348-ba62-f70d13f68dae"
        }
    ],
    "meta": {
        "page_number": 1,
        "page_size": 20,
        "total_pages": 1,
        "total_results": 1
    }
}

Misc: Cancelling a Porting Order

curl --location --request POST 'https://api.telnyx.com/v2/porting_orders/[porting_order_id]/actions/cancel' \
--header 'Authorization: Bearer [REDACTED]'

You can expect the following webhook:

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "73f31498-030a-44a2-9331-0d4cb3a7a766",
    "occurred_at": "2021-03-19T19:49:19.406853Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [],
        "value": "cancel-pending"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-01-19T19:49:18+00:00",
      "webhook_url": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

When the Port Order is actually canceled by admin, you will have the following webhook:

{
  "data": {
    "event_type": "porting_order.status_changed",
    "id": "f0700172-d201-41f7-8be0-f3c08019432f",
    "occurred_at": "2021-03-19T19:55:54.357004Z",
    "payload": {
      "customer_reference": "1-alpha-2-bravo-3-charlie",
      "id": "3594c6c3-51a7-4306-b715-ca3765f13464",
      "status": {
        "details": [],
        "value": "cancelled"
      },
      "support_key": "sr_98f022",
      "updated_at": "2021-03-19T19:55:53+00:00",
      "webhook_url": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://example.com/c49bf044-2ab6-46ee-a148-f8eb40afbd78"
  }
}

Was this page helpful?