
# 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

1. **Start a Porting Request**  
   Begin by creating a [porting][create-a-porting] with the user's phone number, user ID, and recipient provider. Gigs will check if the number is eligible to be ported.

2. **Create a Subscription**  
   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 to `pending` or `informationRequired`.

3. **Submit Required Information**  
   Update the porting to provide all information requested by the API. See the `required` attribute in your porting object as requirements vary by country and provider.

4. **Resolve Issues**  
   If the porting is declined (e.g. due to incorrect information), update the porting with corrected details to retry.

You can also collect all required information before creating the subscription, depending on your workflow and jurisdiction.

<Note type="info">
  Portings have country-specific requirements (e.g. different porting behaviors
  in the United Kingdom). See the bottom of this guide for details.
</Note>

## 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.

<CodeGroup title="Create a porting">

```shell
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"
  }'
```

</CodeGroup>

<Note type="info">
  Draft portings are deleted after 30 days if not used to create a subscription.
</Note>

### 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.

<CodeGroup title="A porting with required parameters">
```json
{
  "object": "porting",
  "id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
  "required": [
    "accountNumber",
    "accountPin",
    "address",
    "firstName",
    "lastName"
  ],
  ...
}
```

</CodeGroup>

Ask the user for this information and update the porting. The porting can't proceed until all required information is provided.

<CodeGroup title="Update a porting">

```shell
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"
  }'
```

</CodeGroup>

### 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.
If information is missing, the status will be `informationRequired`. Continue by updating the porting with the missing details from the `required` property.

<Note>
  The subscription stays `pending` until porting completes or the porting is
  canceled. You can cancel the porting or end the subscription if needed.
</Note>

### 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.

<CodeGroup title="A declined porting with code and message">

```json
{
  "object": "porting",
  "id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
  "status": "declined",
  "declinedCode": "portingPhoneNumberPortProtected",
  "declinedMessage": "The phone number has port protection on the provider.",
  ...
}
```

</CodeGroup>

<Note>
  To retry without changes, update the porting with an empty request. Only do
  this if the decline wasn't due to missing or incorrect information.
</Note>

### 5. Wait for Completion

Once all issues are resolved, the porting will complete and the subscription will activate with the ported number.

<CodeGroup title="A completed porting">

```json
{
  "object": "porting",
  "id": "prt_0SNlurA049MEWV39s2kSYqaat7ZS",
  "status": "completed",
  ...
}
```

</CodeGroup>

## 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][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.                     | Yes                                    |
| `informationRequired` | Missing required information.                                                                                               | Collect and update information to continue.                           | Yes                                    |
| `pending`             | All required information collected. Awaiting Gigs to request the port from the donor provider.                              | No action needed.                                                     | Yes                                    |
| `requested`           | Awaiting processing by providers or scheduled date.                                                                         | No action needed.                                                     | Only if `scheduledOn` is in the future |
| `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`              | Consent request expired or 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 from `requested` or `declined`, since expiry is a donor-side outcome.
- **`failed`** — only appears in markets requiring user consent. The user did not approve the consent request in time, so the port was never requested from the donor provider. Only reachable from `initiated`. 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.
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.

If at any point in this lifecycle the user decides not to port their number, the porting can be canceled.
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.

```mermaid
stateDiagram-v2
  direction LR
  [*]-->draft
  draft-->pending
  draft-->informationRequired
  pending-->requested
  informationRequired-->pending
  declined-->pending
  requested-->completed
  requested-->declined
  declined-->canceled
  informationRequired-->canceled
  completed-->[*]
  canceled-->[*]
```

**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 `pending`, `informationRequired`, and `declined`. A `requested` porting is cancelable only when it is scheduled and the scheduled date is in the future.

```mermaid
stateDiagram-v2
  direction LR
  [*]-->draft
  draft-->pending
  draft-->informationRequired
  pending-->requested
  pending-->declined
  pending-->canceled
  informationRequired-->pending
  informationRequired-->canceled
  declined-->pending
  declined-->informationRequired
  declined-->expired
  declined-->canceled
  requested-->completed
  requested-->declined
  requested-->expired
  requested-->canceled
  completed-->[*]
  canceled-->[*]
  expired-->[*]
```

**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, the porting moves to `pending` (or `informationRequired` if data is still missing). If the user does not approve in time, the porting transitions to `failed`. An `initiated` porting is cancelable.

```mermaid
stateDiagram-v2
  direction LR
  [*]-->draft
  draft-->initiated
  initiated-->pending
  initiated-->informationRequired
  initiated-->canceled
  initiated-->failed
  pending-->requested
  pending-->declined
  pending-->canceled
  informationRequired-->pending
  informationRequired-->canceled
  declined-->pending
  declined-->informationRequired
  declined-->expired
  declined-->canceled
  requested-->completed
  requested-->declined
  requested-->expired
  requested-->canceled
  completed-->[*]
  canceled-->[*]
  expired-->[*]
  failed-->[*]
```

## 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.                    |

## Test Portings

Use our test phone numbers to try porting flows. See the [testing guide][test-phone-numbers] for details.

## Country-specific Considerations

### United Kingdom

See our [UK porting guide][porting-in-the-uk].

### United States

See our [US porting guide][porting-in-the-us].

[porting-in-the-us]: /docs/porting/porting-in-the-us
[porting-in-the-uk]: /docs/porting/porting-in-the-uk
[create-a-porting]: /core/portings#create-a-porting
[create-a-subscription]: /core/subscriptions#create-a-subscription
[request-port-in]: /core/subscriptions#port-a-phone-number-into-a-subscription
[porting-schema]: /core/schemas/porting
[test-phone-numbers]: /docs/core/testing/test-phone-numbers
