Integration guide
Find and display plans
The catalogue is large — a few thousand plans across countries, regions and global packs. Filter it server-side and cache it.
Searching
curl -s "https://app.journeystack.co/api/public/v1/plans?country=SG&type=unlimited&limit=20&page=1" \
-H "Authorization: Bearer $JS_KEY"- country takes an ISO alpha-2 code and is case-insensitive.
- region returns multi-country packs, e.g. EU for Europe, AS for Asia, ME for the Middle East.
- min_days and max_days bound fixed-validity plans.
- type filters fixed versus unlimited, and is applied after the page is read — a page can come back shorter than limit.
- pagination.total is the count before the type filter, so drive your paging from it but do not assume a full page.
Two kinds of plan
A fixed plan is a data bundle with a fixed validity: `data.bytes` is set, `validity.days` is set and `price.per` is `esim`. An unlimited plan is sold per day: `data.bytes` is null, `validity.billed_per_day` is true, and `price.amount` is the price of a single day.
const price = plan.validity.billed_per_day
? plan.price.amount * selectedDays // traveller picks 1–365 days
: plan.price.amount;Always confirm with the order
Describing unlimited fairly
Unlimited plans give a full-speed allowance each day (`data.daily_allowance`) and then continue at a reduced speed (`data.throttled_speed`). Show both — travellers who expect uncapped full speed complain, and the information is in the response for exactly that reason.
Coverage and networks
`coverage.type` is `country` or `region`. To show the carriers an eSIM can roam on, fetch the single plan — `GET /plans/{id}` adds a `networks` array. Regional packs list a carrier per country, which doubles as your country list.
Caching
- Sync the catalogue on a schedule — hourly is plenty — rather than calling /plans on every page view.
- Store the Journey Stack plan ID as your key — it is the only identifier you ever need.
- Re-check a plan before selling it: withdrawn plans start returning not_found on order.
- Prices move with currency rates, so refresh cached prices at least daily.