Skip to content

List packages

GET/v1/catalog/packagescatalog:read

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.

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
Terminal window
curl 'https://partner-api.esimfo.com/v1/catalog/packages?country=TR&limit=50' \
-H 'Authorization: Bearer esf_live_at_...'
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
}

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.

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 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.

Status Code Cause
403 insufficient_scope Key lacks catalog:read
429 rate_limited Over the per-minute allowance