Firsty

Search...

Search...

PortingExperimental

Move the porting moment of an approved port-in

Sets the moment the number moves to scheduledAt, for a port-in the donor approved. Without a move, the number moves at the earliest moment the donor agreed to, the scheduledAt of portin.approved. At that moment the number stops working on the customer's old SIM, so move it later when:

  • the customer wants to switch when their contract at the donor ends, rather than end it early;
  • the SIM the number moves to is not in use yet, such as an eSIM not yet installed or a SIM card on its way;
  • the customer prefers another day.

The moment must fall in the porting window, Monday to Friday from 08:30 to 17:30 Dutch time, and between the earliest moment and 90 days after it; one outside either is refused. Public holidays are outside the porting window too, but a moment on one is not refused. The moment is taken in whole seconds. portin.rescheduled announces the new moment. Available for Dutch numbers.

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

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)

portInRequestReferencestringrequired

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

Headers

X-Idempotency-Keystring

Optional idempotency key for requests that change state. 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 method, path and request body → returns cached response (prevents duplicate operations)
  • Same key + different method, path or request body → returns 422 error
  • Same key + in-flight request → returns 423 error
  • Keys are held for at least 48 hours; use a fresh key for every new request

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 ✓
  • The method and the full path, query included, must match as well; headers are not compared

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

scheduledAtstring · date-timerequired

The moment the number moves, in whole seconds (fractions are dropped); must be in the future

Responses

200The port-in with its new `scheduledAt`application/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 and donorContractAction; a prepaid one refuses donorContractAction. Without donorAccountNumber, the customer confirms the port-in with a code sent by SMS to the number being ported. The request stays requested until they do; an unconfirmed code expires after 24 hours and the port-in is rejected.

Show properties
donorContractTypestring

Contract type of the number at the donor operator

Optionsprepaidpostpaid
donorAccountNumberstringoptional

Customer number at the donor operator

donorContractActionstringoptionalExperimental

Extensible enum. What happens to the customer's contract at the donor operator. Required for a postpaid contract and refused for a prepaid one, which has no contract to end or keep. terminate_at_expiry ends it where it can end; the donor may refuse the port while a commitment period runs. terminate_early ends it even during a commitment period, which may cost the customer an early-termination fee at the donor. keep_with_new_number keeps the contract running at the donor under a new number.

Examplesterminate_at_expiryterminate_earlykeep_with_new_number
statusstring

Extensible enum.

  • requested: Accepted by Firsty; provider submission in progress
  • approved: The donor accepted the port; scheduledAt is the earliest moment the number can move, once known, which can be days ahead. When that moment has already passed, the number moves right after the approval. 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 or abandon (see the Porting workflow). 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 or abandon (see the Porting workflow)
  • cancelled: Cancellation confirmed; submit a corrected request or abandon (see the Porting workflow)
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

The moment the number moves to this SIM. At approval it is the earliest moment the donor agreed to, and a reschedule replaces it with the moment the client chose; null until known. When it has already passed at the approval, the number moves right after. 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 number moved to this SIM

abandonedbooleanoptional

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

createdAtstring · date-time
updatedAtstring · date-time
409The port-in is not approved, or it changed while this request ran: another move, its completion or its cancellationapplication/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_refusedport_in_reschedule_not_supportedport_in_reschedule_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable
422The network refused the moment (`port_in_reschedule_refused`), the eSIM's network does not move port-ins (`port_in_reschedule_not_supported`), or an idempotency key was reused for a different request (`idempotency_key_reused`)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_refusedport_in_reschedule_not_supportedport_in_reschedule_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable
400Bad request - invalid parameters401Unauthorized - missing or invalid API key403Forbidden - client does not have access to this resource404Resource not found423A request with this idempotency key is still being processed429Rate limit exceeded. A `429` can also arrive without these headers or this body; handle it by its status code.500Internal server error503Service temporarily unavailable. Safe to retry.