This guide allows you to move your existing integration from V1 to V2 of the Airalo Partner API. Every v2 endpoint is available at the same path as its v1 equivalent: replace v1 with v2 in the request URL against https://api.partners.airalo.com.Nothing about the requests you send changes. v2 accepts the same request bodies, query parameters, filters and pagination as v1, with the same validation rules.Authentication is unchanged: the access token obtained from the "Request access token" endpoint works exactly as before, with the same credentials and no additional scopes or headers.All of the work described below is in how your integration reads the response. For many of you there is no work at all.For more information and best practices visit our FAQ page.Before you start: endpoints that need no changes#
The following endpoints return an identical response on v2. If these are the only endpoints your integration calls, changing the URL completes your migration.| Endpoint | v2 path |
|---|
| Request access token | POST /v2/token |
| Get order status list | GET /v2/orders/statuses |
| Get installation instructions | GET /v2/sims/{sim_iccid}/instructions |
| Get balance | GET /v2/balance |
| Get co-branded configurations | GET /v2/cobranded/configurations |
Note on compatible devices. GET /v2/compatible-devices returns the same response as v1, but is now deprecated. If you use it, migrate to GET /v2/compatible-devices-lite as part of this upgrade.
Everything that requires attention is on the order, package and eSIM endpoints. Use the endpoint reference at the end of this guide to confirm which changes apply to you.
Changes that require action#
There are ONLY three. Each one lists who it affects, followed by the steps to take.
1. quantity, price and validity are returned as numbers#
On order and top-up responses, v2 returns quantity, price and validity as JSON numbers where v1 returned them as strings. Which fields change depends on the endpoint:| Endpoint | quantity | price | validity |
|---|
| Submit order | Number | Number | Unchanged: a string on both versions |
| Submit top-up order | Number | Number | Number |
| Get order, Get order list | Number | Number | Number |
Integrations written in strictly typed languages — Java, C#, Go, Kotlin, Swift, Rust, or TypeScript with strict runtime validation. If you deserialise responses into a typed model where these fields are declared as strings, or you compare them with strict equality against a quoted value, your integration will fail on v2.Integrations in loosely typed languages such as PHP, Python, Ruby or plain JavaScript are usually unaffected, because these compare and cast loosely. Test rather than assume.What to do#
1.
Change quantity and validity to an integer type in your response model, and price to a decimal number type. Do not use an integer for price: prices carry fractional values such as 4.5.
2.
On "Submit order", validity is still returned as a string. If one model serves both order creation and order retrieval, make validity accept either type.
3.
Remove any string parsing applied to these fields, such as parseInt or equivalent.
4.
Replace any strict comparison against a quoted value. For example, quantity === "2" becomes quantity === 2.
5.
Deserialise a real order response and a real top-up response in your test environment, and confirm all three fields parse without error.
Affected endpoints: "Submit order", "Submit top-up order", "Get order", "Get order list".v1 response v2 response
{ {
"quantity": "2", "quantity": 2,
"validity": "7", "validity": 7,
"price": "4.50" "price": 4.5
} }
2. The order key is no longer returned in the eSIMs list#
On the "Get eSIMs list" endpoint, each item in data previously included an order key whose value was always null. In v2 this key is not returned at all.Integrations that read order from eSIM list items, or that require the key to be present when deserialising the response. Because the value was always null on v1, no information is lost.What to do#
1.
Remove any reference to data[].order in your handling of the "Get eSIMs list" response.
2.
If your deserialiser requires the key to be present, mark it optional or remove it from your model.
3.
If you need order information for an eSIM, request it explicitly using the include parameter documented on the "Get eSIMs list" endpoint.
Affected endpoints: "Get eSIMs list".
3. Error responses return a specific code instead of a generic failure#
This is the largest change, and the most valuable one. On v1, an order that fails during processing returns a generic server error (HTTP 500) that does not say why. Insufficient balance is the one exception: since October 2026 it returns HTTP 402, still without a code. v2 returns the specific reason as a numeric code with HTTP status 422, including insufficient balance, which becomes code 11.HTTP/1.1 422 Unprocessable Entity
{
"code": 11,
"reason": "Insufficient balance"
}
Every integration that submits orders or top-ups and inspects the failure response — in particular any logic that matches on the v1 failure message text, which will no longer match anything, and any logic that branches on v1's HTTP 402 or 500 status.What to do#
1.
Replace any check against the v1 failure message with a branch on the numeric code field.
2.
Handle at least the following codes, and apply the retry behaviour shown:
code | Meaning | How to respond |
|---|
11 | Insufficient balance | Top up your balance before retrying. Do not retry immediately. |
13 | Operator is in maintenance | Temporary. Retry later using backoff. |
33 / 34 | Requested quantity is not available | Reduce the quantity or select another package. |
43 | Validation error | Correct the request. Do not retry it unchanged. |
83 | An identical request was received within the last second | See below. |
Step 3. Handle code 83 explicitly. v2 rejects a byte-identical order or top-up payload received within one second of the previous one, to protect you against accidental duplicate orders. If your integration uses a retry loop, or submits batches of identical orders in sequence, treat 83 as "the previous request may have succeeded": check the order status before retrying, and add either a short delay or a distinguishing value between requests.Step 4. Make sure an unrecognised code does not throw. Log it and fail safely so that new codes never break your integration.Consult the error handling reference for the complete and current list of codes.
New data in v2#
v2 returns additional fields and values that v1 did not. Nothing is renamed or removed, so a tolerant integration is unaffected and no action is required. This introduces ZERO breaking changes.Only integrations configured to reject unrecognised data — a JSON schema using additionalProperties: false, or a deserialiser that raises an error on unknown properties. These will fail on the additional fields below.What to do#
1.
Configure your deserialiser to ignore unknown properties.
2.
Make sure any order status mapping falls through safely to a default instead of raising an error, so that unrecognised values are handled gracefully.
Once both are in place, future additive changes to the API will not require any work from you.voice and text: allowances on packages and usage responses, alongside the existing data allowance.
net_price, and a prices object containing per-currency values.
pricing: a top-level object on "Get packages", "Get eSIM package history" and "Get top-up package list". The data array itself is unchanged.
APN settings per operating system, and msisdn on eSIM responses.
direct_apple_installation_url, and eSIM sharing links.
recycled and recycled_at on eSIM responses.
Order status may include refunded and partially_refunded.
Two behaviour differences worth testing#
These are not errors, but the values returned may differ from v1 for the same request."Get usage (data, text & voice)": for unlimited packages, remaining and total are returned as 0, and status is recalculated. If you display usage for unlimited plans, confirm how this renders in your interface.
"Get top-up package list": the filter[country] parameter is now applied. v1 accepted the parameter but ignored it, so you may receive fewer results than before. This is the intended behaviour.
What you gain on v2#
Specific error reasons instead of a single generic failure, so your integration can retry appropriately rather than guessing.
A higher rate limit on "Get packages" — 80 requests per minute, increased from 50.
Accept-Language support, so package and order content is returned translated. v1 ignores this header.
eSIM sharing at order time using to_email and sharing_option, and custom branding using brand_settings_name.
Endpoints available only on v2: "Submit order async", "Future orders", "Cancel future orders", "Request refund", "eSIM voucher", and package overrides.
Support for discount pricing, which is not available on v1.
Endpoint reference#
| Endpoint | v2 path | Changes that apply |
|---|
| Request access token | POST /v2/token | None |
| Get order status list | GET /v2/orders/statuses | None |
| Get installation instructions | GET /v2/sims/{sim_iccid}/instructions | None |
| Get balance | GET /v2/balance | None |
| Get co-branded configurations | GET /v2/cobranded/configurations | None |
| Get compatible device list | GET /v2/compatible-devices | None, but deprecated — move to compatible-devices-lite |
| Submit order | POST /v2/orders | New data |
| Submit top-up order | POST /v2/orders/topups | New data |
| Get order list | GET /v2/orders | New data |
| Get order | GET /v2/orders/{order_id} | New data |
| Get packages | GET /v2/packages | New data |
| Get eSIMs list | GET /v2/sims | New data |
| Get eSIM | GET /v2/sims/{sim_iccid} | New data |
| Get usage (data, text & voice) | GET /v2/sims/{sim_iccid}/usage | New data, unlimited-plan values differ |
| Get eSIM package history | GET /v2/sims/{iccid}/packages | New data |
| Get top-up package list | GET /v2/sims/{iccid}/topups | New data, country filter now applies |
Before you move production traffic to v2#
If you would like us to confirm which of these changes apply to your specific integration, contact your Airalo account manager and we will review it with you. Modified at 2026-10-15 14:52:11