Top up an eSIM
const url = 'https://api.roamex.com/v1/esims/topup?lang=nl';const options = { method: 'POST', headers: { 'Idempotency-Key': 'topup-2026-10-22-0001', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '{"esimId":"00000000-0000-4000-8000-0000000000c1","packageId":"pkg_EXAMPLE.TOKEN.VALUE"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url 'https://api.roamex.com/v1/esims/topup?lang=nl' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: topup-2026-10-22-0001' \ --data '{ "esimId": "00000000-0000-4000-8000-0000000000c1", "packageId": "pkg_EXAMPLE.TOKEN.VALUE" }'Adds a top-up package to an existing eSIM and pays from your balance. The traveller keeps the same eSIM. packageId must be an id from /esims/topup-options.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Language of plan and destination names in the response: en, nl, es, de, it, fr, pl, pt, tr, el, cs or ro. Any other value, or none, gives English. It never changes which items are returned or any figure.
Example
nlHeader Parameters
Section titled “Header Parameters”Makes retries safe. The key is combined with your account, the eSIM and the package. A repeat is answered with a 409 and is not charged again: DUPLICATE_REQUEST once the top-up was applied, ORDER_IN_PROGRESS while it is open, ORDER_TERMINAL when it failed. Without this header, a repeat of the same top-up within 60 seconds, or while the first is still open, is answered the same way.
Example
topup-2026-10-22-0001Request Bodyrequired
Section titled “Request Bodyrequired”object
A package id from /esims/topup-options.
Example
{ "esimId": "00000000-0000-4000-8000-0000000000c1", "packageId": "pkg_EXAMPLE.TOKEN.VALUE"}Responses
Section titled “Responses”The top-up was applied.
object
object
object
A fresh package token. It is not the same string you sent.
object
0 when unknown.
Two decimals in GB, whole numbers in MB and KB, 0 B when unknown.
object
What your balance was charged.
object
Euro cents.
object
Euro cents.
Example
{ "success": true, "topup": { "package": { "id": "pkg_EXAMPLE.TOKEN.OTHER", "name": "Japan · 1 GB · 7 days", "data": { "bytes": 1073741824, "formatted": "1.00 GB" }, "validity": { "days": 7, "unit": "DAY" } }, "cost": { "amount": 450, "currency": "EUR", "formatted": "€4.50" } }, "newBalance": { "amount": 23650, "currency": "EUR", "formatted": "€236.50" }}Headers
Section titled “Headers”Calls allowed per minute for this endpoint group.
Calls left in the current minute.
When the current window ends, in Unix seconds.
INVALID_JSON: the body is missing or not a JSON object.MISSING_ESIM_ID:esimIdis missing or not a string.MISSING_PACKAGE_ID:packageIdis missing or not a string.INVALID_PACKAGE_ID:packageIdis not a token from/esims/topup-options, or it was altered.ESIM_CANCELLED: the eSIM is cancelled.ESIM_NOT_READY: the eSIM is not provisioned yet.NO_TOPUP_OPTIONS: top-ups are not available for this eSIM.INVALID_PACKAGE: the package is not available for this eSIM.UNSUPPORTED_PACKAGE: the package is a day-pass extension, which the API does not sell.INSUFFICIENT_BALANCE: your balance does not cover the top-up. Nothing was charged.TOPUP_FAILED: the top-up was refused and no data was added.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}AUTH_ERROR: the key is missing, malformed, unknown or revoked. The message says which, for example Missing Authorization header, Invalid Authorization header format. Use: Bearer <api_key>, Invalid API key format or Invalid API key.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false, "error": { "code": "AUTH_ERROR", "message": "Invalid API key" }}DESTINATION_NOT_ALLOWED: the eSIM’s destination is not on your account’s list of allowed destinations.SPEND_CAP_EXCEEDED: the top-up would take you over your account’s monthly spend limit.TRIAL_RESTRICTED: trial accounts cannot top up.AUTH_ERROR: the account is suspended or not approved.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}ESIM_NOT_FOUND: no eSIM with this id belongs to your account.NOT_FOUND: the API is switched off on the platform.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}ESIM_EXPIRED: the eSIM’s validity has ended.TOPUP_LIMIT_REACHED: the eSIM already has 9 top-ups, the most it accepts. Order a new eSIM instead.ORDER_IN_PROGRESS: an identical top-up, or an earlier top-up on this eSIM, has not finished./esims/detailsshows the data grow when it lands, and theesim.topped_upevent arrives by webhook and in/events/recent.DUPLICATE_REQUEST: this top-up was already submitted.ORDER_TERMINAL: the earlier identical request failed and applied no data.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}PAYLOAD_TOO_LARGE: the Content-Length header is over 100 KB.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}RATE_LIMITED: the account’s per-minute budget for this endpoint group is used up, or too many refused keys came from this IP address. Wait the Retry-After seconds.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Please wait 42 seconds before retrying." }}Headers
Section titled “Headers”Calls allowed per minute for this endpoint group.
Calls left in the current minute.
When the current window ends, in Unix seconds.
Seconds to wait before retrying.
TOPUP_FAILED: the top-up could not be processed, or it may have been applied but not recorded. The message says which. Check the eSIM with/esims/detailsbefore retrying.INTERNAL_ERROR, orAUTH_ERRORwith status 500: see the shared errors.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}TOPUP_OUTCOME_UNKNOWN: the top-up was sent but no answer came back. Your balance stays charged while the eSIM is checked, and the charge is returned if the data did not arrive.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}Transient. Your balance is not charged for these.
PURCHASES_PAUSED: purchases are paused. Retry after theRetry-Afterseconds.TOPUP_OPTIONS_UNAVAILABLE: the top-up options could not be loaded.PRICING_UNAVAILABLE: your account pricing could not be confirmed.
object
object
Machine-readable. Branch on this.
A sentence for people. It can change.
Example
{ "success": false}Headers
Section titled “Headers”Seconds to wait. Sent with PURCHASES_PAUSED (300).

