How Porting In Works
This guide walks you through the process of porting a phone number to Gigs using the Gigs API. Follow these steps to ensure a smooth port-in experience for your users.
Step-by-Step Porting Guide
-
Start a Porting Request
Begin by creating a porting with the user's phone number, user ID, and recipient provider. Gigs will check if the number is eligible to be ported. -
Create a Subscription
Create a subscription and reference the porting. If you skip this, a new number will be assigned. The porting status will update topendingorinformationRequired. -
Submit Required Information
Update the porting to provide all information requested by the API. See therequiredattribute in your porting object as requirements vary by country and provider. -
Resolve Issues
If the porting is declined (e.g. due to incorrect information), update the porting with corrected details to retry. Amanualporting must also be requested again.
You can also collect all required information before creating the subscription, depending on your workflow and jurisdiction.
Portings have country-specific requirements (e.g. different porting behaviors in the United Kingdom). See the bottom of this guide for details.
Porting In Process
1. Create a Porting
Create a porting with the desired phone number and provider ID.
On creation, Gigs will check if the provider can accept the number.
If eligible, you'll get a porting with draft status.
To let users confirm their details before the porting is submitted, create it with a requestBehavior of manual (see choosing when a porting is requested).
Create a porting
curl --request "POST" \
--url "https://api.gigs.com/projects/${GIGS_PROJECT}/portings" \
--header "Accept: application/json" \
--header "Authorization: Bearer ${GIGS_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"phoneNumber": "+19591234567",
"provider": "p4",
"user": "usr_0SNlurA049MEWV4OpCwsNyC9Kn2d"
}'
Draft portings are deleted after 30 days if not used to create a subscription.
2. Collect Required Information
Gather the necessary details from the user. The API will list required fields in the required property.
For example, US-based providers typically require the current account holder's name, account number and account pin. In some cases, the billing address may also be required.
A porting with required parameters
{
"object": "porting",
"id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
"required": [
"accountNumber",
"accountPin",
"address",
"firstName",
"lastName"
],
...
}
Ask the user for this information and update the porting. The porting can't proceed until all required information is provided.
Update a porting
curl --request PATCH \
--url "https://api.gigs.com/projects/${GIGS_PROJECT}/portings/${PORTING_ID}" \
--header "Accept: application/json" \
--header "Authorization: Bearer ${GIGS_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"accountNumber": "123456789",
"accountPin": "1234",
"address": {
"city": "New York City",
"country": "US",
"line1": "129 West 81st Street",
"line2": "Apartment 5",
"postalCode": "10024",
"state": "NY"
},
"firstName": "Jerry",
"lastName": "Seinfeld"
}'
3. Create a Subscription
Create a subscription with the porting to start the process. The porting status will update to pending if all information is present and the requestBehavior is automatic.
If information is missing, the status will be informationRequired. Continue by updating the porting with the missing details from the required property.
A manual porting stays informationRequired until you request it.
The subscription stays pending until porting completes or the porting is
canceled. You can cancel the porting while it's in a cancelable status (see the status table below), or end the subscription if needed.
4. Handle Issues
If declined, the porting will show a code and message. Update the porting with corrected information to retry.
Keep an eye on the required property in case additional information is needed.
A declined porting with code and message
{
"object": "porting",
"id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
"status": "declined",
"declinedCode": "portingPhoneNumberPortProtected",
"declinedMessage": "The phone number has port protection on the provider.",
...
}
Only retry without changes if the decline wasn't due to missing or incorrect
information. For an automatic porting, update it with an empty request. For
a manual porting, an update doesn't
resubmit it, so request the porting again.
5. Wait for Completion
Once all issues are resolved, the porting will complete and the subscription will activate with the ported number.
A completed porting
{
"object": "porting",
"id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
"status": "completed",
...
}
Choosing When a Porting Is Requested
By default, a porting moves to pending as soon as it has all required information and is attached to a subscription, so the update that fills in the last required field starts the port. To let users confirm their details first, set the porting's requestBehavior to manual and request the porting yourself once they do.
requestBehavior and the request a porting endpoint
are in preview and might change in the future.
Use automatic (the default) if the update that completes the porting is the user's go-ahead, for example a single form they submit. Use manual if you save details before the user has confirmed them, for example across several screens or to show a review page.
automatic | manual | |
|---|---|---|
| All required information present | Moves to pending | Stays informationRequired until requested |
| Updated after a decline, including with an empty update | Resubmitted | Stays declined until requested |
| Request a porting | Fails | Moves to pending |
informationRequired events and reminders | Only while information is missing | Also while waiting to be requested |
Requesting a Manual Porting
Create the porting with a requestBehavior of manual, or update an existing porting while it can still be edited. Then create the subscription and collect the required information as usual.
Create a manual porting
curl --request "POST" \
--url "https://api.gigs.com/projects/${GIGS_PROJECT}/portings" \
--header "Accept: application/json" \
--header "Authorization: Bearer ${GIGS_TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"phoneNumber": "+19591234567",
"provider": "p11",
"requestBehavior": "manual",
"user": "usr_0SNlurA049MEWV4OpCwsNyC9Kn2d"
}'
The porting is ready to request when its status is informationRequired or declined and every field listed in required has a value. required lists all the fields the providers need, not only the missing ones, and status alone doesn't tell you whether anything is missing, so compare the two before asking the user for more. PINs are never returned, so check accountPinExists and billingPinExists instead, and donorProviderApproval must be true. Show the user their details and, once they confirm, request the porting.
Request a porting
curl --request POST \
--url "https://api.gigs.com/projects/${GIGS_PROJECT}/portings/${PORTING_ID}/request" \
--header "Accept: application/json" \
--header "Authorization: Bearer ${GIGS_TOKEN}"
The porting moves to pending and is returned in that status. If the request fails with portingAlreadyRequested, the porting is already pending or requested, for example after a double tap, and you can treat it as a success. For portingNotRequestable, the error's hint says why.
If the porting is declined, update it with the corrected details, have the user confirm them, and request it again.
Switching a manual porting that is waiting to be requested
(informationRequired or declined) back to automatic moves it to
pending straight away, without a request.
Porting Lifecycle
Porting involves several parties and can take minutes to days. The status field tracks progress.
Porting Statuses
Below is a summary of each porting status and what to do next. The cancelable column indicates whether a porting can be canceled in that status.
| Status | Description | Action | Cancelable |
|---|---|---|---|
draft | Porting not used in a subscription yet. | Create a subscription or request port-in to start. | No |
initiated | Awaiting end-user consent. Only appears in markets requiring user consent. | Wait for the user to approve the consent request. If it expires, create a new one from it to retry. | Yes |
informationRequired | Missing required information, or a manual porting waiting to be requested. | Collect and update information to continue. If a manual porting has every required field, request it once the user confirms. | Yes |
pending | All required information collected. Awaiting Gigs to request the port from the donor provider. | No action needed. | No |
requested | Awaiting processing by providers or scheduled date. | No action needed. | Only if scheduledOn is in the future and within the provider's cancellation window (varies by provider) |
declined | Declined by provider, with reason code/message. | Review reason, update information, and retry. | Yes |
completed | Porting finished successfully. | No action needed. | No |
canceled | Porting canceled. Subscription activates with new number. | No action needed. | No |
expired | Porting expired at the donor provider. | Start over with a new porting and subscription. | No |
failed | No consent was given in time, the user ran out of code attempts, or the consent request was canceled, before the port could be requested. Only appears in markets requiring user consent. | Start over with a new porting and subscription. | No |
Resolved States
Once a porting reaches one of completed, canceled, expired, or failed, it never transitions again. The four resolved states differ by who ended the porting and why:
completed— the donor provider confirmed the port and the number is now active on Gigs. The associated subscription activates with the ported number.canceled— the porting was canceled either explicitly via the API, or implicitly when the parent subscription ended while the porting was still unresolved. The subscription activates with a new number if the port had not yet completed.expired— the donor provider's window to act on the port closed before the port could complete. Only reachable fromrequestedordeclined, since expiry is a donor-side outcome.failed— only appears in markets requiring user consent. No consent request for the porting was approved in time, the user ran out of code attempts, or the consent request was canceled, so the port was never requested from the donor provider. Only reachable frominitiated. The subscription was never activated against this porting.
lastDeclinedAt and declinedAttempts
lastDeclinedAt is a historical timestamp, not a state indicator. It records the most recent time the porting transitioned into declined. Once set, it persists for the lifetime of the porting — it is never cleared, even when the porting moves out of declined (back to pending via an update, or onward to completed, canceled, expired, or failed). A porting can therefore have a non-null lastDeclinedAt while its current status is completed.
declinedAttempts is a cumulative counter incremented on each transition into declined. Together, the two fields let you answer "has this porting ever been declined, and when most recently?" without having to scan event history.
To check whether a porting is currently in the declined state, read status, not lastDeclinedAt.
State Diagrams
Simplified Porting Lifecycle
The following state diagram shows the typical porting process with back and forth between user and donor provider or recipient provider. Ultimately, the porting is either completed successfully or canceled by the user.
After creation, the porting is in draft mode. It stays in draft mode until it is referenced in a subscription.
From there, the porting either moves to informationRequired if required information is missing or to pending if all information is present.
Once it is in pending, our system starts processing the porting and requesting the porting from the carrier.
After the port has been successfully processed, it moves to completed or if the port has been declined by the provider it moves to declined.
When declined, the porting moves back to pending once the porting is updated via the API and we start processing the porting again.
This loop continues until the porting is successfully completed.
A manual porting moves to pending only when you request it.
If the user decides not to port their number, the porting can be canceled, depending on its current status. A cancellation of the porting leads to the activation of the attached subscription with a new number. See the cancelable column in the status table above for the precise rules.
Standard Porting Lifecycle
The following state diagram displays the full porting lifecycle in markets that do not require explicit user consent. We do not recommend to hardcode these state transitions.
Cancellation is permitted from informationRequired and declined. A requested porting is cancelable only when it is scheduled, the scheduled date is in the future, and it is within the provider's cancellation window.
Porting Lifecycle in Markets Requiring User Consent
In markets that require explicit user consent before contacting the donor provider, the porting begins in initiated while the consent request is outstanding. Once the user approves, an automatic porting with all required information moves to pending. Otherwise, it moves to informationRequired, where a complete manual porting waits to be requested. An expired consent request alone doesn't fail the porting: the porting stays initiated, and a new consent request can be created from the expired one to retry. If no consent request is approved in time, the porting transitions to failed. An initiated porting is cancelable.
Porting Decline Codes
Here are the possible decline codes and their meanings. Your app should handle new codes as they are added.
| Code | Description |
|---|---|
portingDeclined | Unknown reason. Contact support. |
portingPhoneNumberNotEligible | Number not eligible for porting. |
portingPhoneNumberNotFound | Number not found with donor carrier. |
portingSameNewAndOldNetworkProvider | Same provider for donor and recipient. |
portingUserInformationMismatch | Information mismatch with donor carrier records. |
portingPhoneNumberNotActive | Number not active with donor carrier. |
portingPhoneNumberAdministrative | Number reserved for carrier use. |
portingPendingOtherProvider | Active porting request exists with another carrier. |
portingDuplicated | Pending porting request already exists. |
portingPhoneNumberPortProtected | Port protection enabled. |
portingAccountPinRequiredOrInvalid | Account PIN required or invalid. |
portingAccountNumberRequiredOrInvalid | Account number required or invalid. |
portingAddressRequiredOrInvalid | Address required or invalid. |
portingPostalCodeRequiredOrInvalid | Postal code required or invalid. |
portingFirstNameRequiredOrInvalid | First name required or invalid. |
portingLastNameRequiredOrInvalid | Last name required or invalid. |
portingBillingPinRequiredOrInvalid | Billing pin required or invalid. |
portingSingleMultiLineTypeMismatch | Single or multi-line account type doesn't match donor records. Ireland only. |
portingPrepaidPostpaidTypeMismatch | Prepaid or postpaid account type doesn't match donor records. Ireland only. |
portingRegisteredUnregisteredTypeMismatch | Registered or unregistered account type doesn't match donor records. Ireland only. |
Test Portings
Use our test phone numbers to try porting flows. See the testing guide for details.
Country-specific Considerations
France
Portings in France can be scheduled with scheduledOn. Ports are processed on open days only: Monday to Saturday, excluding French public holidays. If the requested date falls on a Sunday or a public holiday, the porting is moved to the next open day rather than rejected.
The date must be at least 3 open days and at most 59 calendar days after the request. Dates outside this window are rejected when the porting is created or updated. See our France porting guide for details.
United Kingdom
See our UK porting guide.
United States
See our US porting guide.