Firsty

Search...

Search...

PortingExperimental

Create a corrected port-in request

Creates and submits a new port-in request for the eSIM. Use this after a previous request ended rejected, failed, or cancelled (e.g. with corrected donor details), or to start porting on an eSIM that can still port (see the Porting tag). The previous terminal request is superseded (marked abandoned), so only the newest request is ever live.

Rejected when the eSIM can no longer port, when a request is still in progress, or when the eSIM's porting was abandoned.

For the initial port-in, prefer the portIn block on POST /esims — it guarantees an eSIM that waits for its port cannot activate before the port-in is registered. Any numberRegistration supplied with that initial order carries over to a corrected request automatically, tracking the corrected number; this endpoint takes no registration details of its own.

post/profiles/{profileReference}/esims/{esimReference}/port-ins

Authorization

Authorization: Bearer {token} — an OAuth2 access token from the client-credentials flow. How authentication works

Path parameters

profileReferencestringrequired

The eSIM's profile reference (16-digit numeric string)

esimReferencestringrequired

eSIM reference identifier (18-digit opaque token)

Headers

X-Idempotency-Keystring

Optional idempotency key for mutating requests (POST, PATCH). If provided, duplicate requests with the same key within 48 hours will return the cached original response without duplicating side effects.

Behavior:

  • Same key + same request body → returns cached response (prevents duplicate operations)
  • Same key + different request body → returns 422 error
  • Same key + in-flight request → returns 409 error with Retry-After header
  • Keys expire after 48 hours

Request Body Matching: Request bodies are compared by their JSON content. Object key order, including in nested objects, and whitespace do not affect matching. This means:

  • {"a":1,"b":2} and {"b":2,"a":1} are treated as identical ✓
  • Whitespace differences are ignored ✓
  • URL parameters and headers are NOT included in request body matching

Best Practices:

  • Use UUIDs or client-generated unique strings
  • Store keys on your side to support retries
  • Don't reuse keys across different operations

Request body

application/json · required

msisdnstringrequired

The number to port, in international format (E.164 without a leading +) — i.e. the country code, not the national 0 trunk prefix. Belgium: 324 + 8 digits, e.g. 32470123456; Netherlands: 316 + 8 digits, e.g. 31612345678.

detailsone of Belgium | Netherlandsrequired

Donor details of the number to port. Their shape depends on the country of the selected eSIM's variant: the Belgian or the Dutch shape. Unknown fields are rejected.

Show properties
Belgiumobject

Donor details of a Belgian number. A prepaid contract takes donorIccid and/or donorSimNumber; a postpaid contract any of donorIccid, donorSimNumber and donorAccountNumber; a business contract donorAccountNumber only.

Show properties
donorContractTypestringrequired

Contract type of the number at the donor operator

Optionsprepaidpostpaidbusiness
donorIccidstring

ICCID of the donor SIM card, with a valid check digit. The preferred proof of a donor SIM: most donor operators accept it.

donorSimNumberstring

The number printed on the donor SIM card. Send it only when the donor SIM's ICCID is not available; donorIccid is accepted by more donor operators.

donorAccountNumberstring

Account/customer number at the donor operator

Netherlandsobject

Donor details of a Dutch number. A postpaid contract requires donorAccountNumber.

Show properties
donorContractTypestringrequired

Contract type of the number at the donor operator

Optionsprepaidpostpaid
donorAccountNumberstring

Customer number at the donor operator

Responses

201Port-in request created and submittedapplication/json
Show response body
dataobjectoptional
Show properties
portInRequestReferencestring

Public opaque port-in request reference (8-char uppercase base36)

profileReferencestring
esimReferencestring

The eSIM this port-in belongs to

msisdnstring

The number being ported, in international format (E.164 without a leading +)

detailsone of Belgium | Netherlandsoptional

Donor details of the number to port. Their shape depends on the country of the selected eSIM's variant: the Belgian or the Dutch shape. Unknown fields are rejected.

Show properties
Belgiumobjectoptional

Donor details of a Belgian number. A prepaid contract takes donorIccid and/or donorSimNumber; a postpaid contract any of donorIccid, donorSimNumber and donorAccountNumber; a business contract donorAccountNumber only.

Show properties
donorContractTypestring

Contract type of the number at the donor operator

Optionsprepaidpostpaidbusiness
donorIccidstringoptional

ICCID of the donor SIM card, with a valid check digit. The preferred proof of a donor SIM: most donor operators accept it.

donorSimNumberstringoptional

The number printed on the donor SIM card. Send it only when the donor SIM's ICCID is not available; donorIccid is accepted by more donor operators.

donorAccountNumberstringoptional

Account/customer number at the donor operator

Netherlandsobjectoptional

Donor details of a Dutch number. A postpaid contract requires donorAccountNumber.

Show properties
donorContractTypestring

Contract type of the number at the donor operator

Optionsprepaidpostpaid
donorAccountNumberstringoptional

Customer number at the donor operator

statusstring

Extensible enum.

  • requested: Accepted by Firsty; provider submission in progress
  • approved: The donor accepted the port; scheduledAt is when the number moves, once known, which can be days ahead. The port finishes at completed
  • cancelling: Cancellation requested, awaiting provider confirmation
  • completed: The donor released the number and it is assigned to this SIM
  • rejected: Donor rejected the request (see reason); submit a corrected request. A rejection the customer can still correct may keep the request requested until it is final
  • failed: Port failed (see reason); submit a corrected request
  • cancelled: Cancellation confirmed; the eSIM stays pre-active for a corrected request or abandon
Examplesrequestedapprovedcancellingcompletedrejectedfailedcancelled
reasonobjectoptional

Why the port-in was rejected or failed. Present when status is rejected or failed, and on a requested port-in the donor has rejected for a reason the customer can still correct

Show properties
codestring

Normalized cause of the rejection or failure, the same for every porting provider. provider_failure covers every cause without a more specific code. The list of values is open-ended; new values may be added

Examplesmsisdn_sim_mismatchmsisdn_account_mismatchdonor_contract_type_mismatchnumber_not_activenumber_not_portablenumber_porting_in_progressporting_window_unavailableprovider_failure
messagestring | null

Human-readable detail of the cause for support; free-form, not intended to be parsed. Null when there is none

scheduledAtstring | null · date-time

When the number moves to this SIM, as the donor agreed when it approved the port; null until known. It may move until the port completes

submittedAtstring | null · date-time

When the port-in was submitted to the provider; null while submission is still pending, and for a port-in whose request was not accepted

completedAtstring | null · date-time

When the port completed

abandonedbooleanoptional

Whether porting was abandoned in favour of the temporary number (irreversible; no corrected request possible)

createdAtstring · date-time
updatedAtstring · date-time
400Validation failed (number format, donor detail rules for the eSIM variant)application/problem+json
Show response body
typestring · uri

URI reference to error documentation

titlestring

Short, consistent error summary

statusinteger

HTTP status code

detailstring

Human-readable explanation specific to this occurrence

codestring

Extensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.

Examplesbad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable
409eSIM can no longer port, its number has already been ported, or the latest request was abandoned (`invalid_state_transition`), or a non-terminal request exists (`port_in_pending`)application/problem+json
Show response body
typestring · uri

URI reference to error documentation

titlestring

Short, consistent error summary

statusinteger

HTTP status code

detailstring

Human-readable explanation specific to this occurrence

codestring

Extensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.

Examplesbad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable
422The eSIM variant does not support porting (`porting_not_supported`)application/problem+json
Show response body
typestring · uri

URI reference to error documentation

titlestring

Short, consistent error summary

statusinteger

HTTP status code

detailstring

Human-readable explanation specific to this occurrence

codestring

Extensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.

Examplesbad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable
401Unauthorized - missing or invalid API key403Forbidden - client does not have access to this resource404Resource not found429Rate limit exceeded. A `429` can also arrive without these headers or this body; handle it by its status code.500Internal server error