List packages
Returns the packages available to your account, priced for your account.
This endpoint returns a flat package list. For catalogs with nested
packages[], use List catalogs with packages.
A package is available when it is on sale in at least one catalog — the curated groups (Türkiye, Europe, Global…) our team assembles. A package taken off every catalog disappears from this list; top-ups are exempt, so an eSIM you already sold can always be topped up.
Query parameters
Section titled “Query parameters”| Name | Type | Default | Notes |
|---|---|---|---|
country |
string | — | ISO 3166-1 alpha-2, e.g. TR. Case-insensitive. Returns packages covering that country, including regional and global ones |
type |
string | esim |
esim, topup-esim or all. See below |
coverage |
string | — | local, regional or global — filters by the catalog the package is sold in. See below |
catalog |
string | — | A catalog id — the key of a regional or global row from List coverage. Returns the packages sold under that catalog |
limit |
integer | 50 | Maximum 200 |
cursor |
string | — | next_cursor from the previous page |
curl 'https://partner-api.esimfo.com/v1/catalog/packages?country=TR&limit=50' \ -H 'Authorization: Bearer esf_live_at_...'Response 200
Section titled “Response 200”| Field | Type | Notes |
|---|---|---|
data[].id |
string | Pass this as package_id when ordering |
data[].type |
enum | esim creates a new eSIM; topup-esim loads onto an existing one |
data[].coverage |
enum | local, regional or global — how wide the package reaches |
data[].name |
string | Display name |
data[].service_type |
enum | DATA or DATA_VOICE_SMS |
data[].data_policy |
enum | FIXED or UNLIMITED |
data[].has_number |
boolean | Whether the eSIM carries a phone number |
data[].data_amount_mb |
integer | null | null when data_policy is UNLIMITED |
data[].validity_days |
integer | Days from activation, not from purchase |
data[].countries |
string[] | ISO alpha-2 codes covered |
data[].networks |
array | Which network the eSIM uses in each country — { country, name, types } |
data[].currency |
string | ISO 4217 |
data[].price |
string | What you pay. Decimal string |
data[].selling_price |
string | null | What you charge. null if selling prices are hidden for your account — the field is always present |
next_cursor |
string | null | Pass as cursor for the next page |
has_more |
boolean | Whether another page exists |
{ "data": [ { "id": "pkg_tr_3gb_30d", "type": "esim", "coverage": "local", "name": "Turkey 3 GB — 30 days", "service_type": "DATA", "data_policy": "FIXED", "has_number": false, "data_amount_mb": 3072, "validity_days": 30, "countries": ["TR"], "networks": [ { "country": "TR", "name": "Turkcell", "types": ["4G", "5G"] } ], "currency": "EUR", "price": "4.20", "selling_price": "6.30" }, { "id": "pkg_eu_unl_15d", "type": "esim", "coverage": "regional", "name": "Europe Unlimited — 15 days", "service_type": "DATA_VOICE_SMS", "data_policy": "UNLIMITED", "has_number": true, "data_amount_mb": null, "validity_days": 15, "countries": ["AT", "BE", "DE", "ES", "FR", "IT", "NL", "PT"], "networks": [ { "country": "DE", "name": "Telekom", "types": ["4G", "5G"] }, { "country": "FR", "name": "Orange", "types": ["4G"] } ], "currency": "EUR", "price": "18.90", "selling_price": "27.40" } ], "next_cursor": "pkg_eu_unl_15d", "has_more": true}Two kinds of package
Section titled “Two kinds of package”esim packages create a new eSIM. topup-esim packages load onto an
existing one and cannot be bought on their own.
The default is esim, deliberately: a mixed list would make you filter out
rows you cannot order. To top up, list what a specific line can take with
List top-ups — availability depends on the eSIM’s
operator and state, not on the catalog.
How wide a package reaches
Section titled “How wide a package reaches”coverage is a separate axis from type: type says what a package
does, coverage says where it works.
| Value | Meaning |
|---|---|
local |
A single country |
regional |
A group of countries — Europe, Asia, LATAM |
global |
Worldwide |
The response field is derived from how many countries the package
covers, not stored, so it can never disagree with countries.
The query parameter filters by something else: the catalog the package
is sold in. Our team curates packages into local, regional and global
catalogs, and ?coverage=regional returns what is on the regional shelf.
The two usually agree, but not always — a package covering most of the
world can be sold in a regional catalog, in which case ?coverage=regional
returns it with "coverage": "global" in the body. Filter by where it is
sold; read the field for where it works.
Networks
Section titled “Networks”networks says which operator’s network the eSIM uses in each covered
country, and which technologies it carries:
"networks": [ { "country": "TR", "name": "Turkcell", "types": ["4G", "5G"] }, { "country": "DE", "name": "Telekom", "types": ["5G"] }]A country can appear more than once when several networks are available. An empty array means the provider does not publish coverage for that package — not that there is none.
price is yours, not a list price. It already reflects your tier and any
account-specific discount. Two partners calling this endpoint see different
numbers for the same package.
Handle data_amount_mb: null. Unlimited packages carry no byte figure.
Formatting it blindly is the most common integration bug here — check
data_policy first.
Validity counts from activation. A 30-day package bought today and installed next month expires 30 days after that.
Cache this. The catalog changes rarely and this is the endpoint most likely to burn your rate limit. Refresh on a schedule, not per page view.
Errors
Section titled “Errors”| Status | Code | Cause |
|---|---|---|
| 403 | insufficient_scope |
Key lacks catalog:read |
| 429 | rate_limited |
Over the per-minute allowance |
