Getting started
First sandbox order
Five calls take you from an API key to an installable eSIM. Everything below runs against the sandbox and costs nothing.
What you need
0. Set your key
export JS_KEY="js_test_your_sandbox_key_here"1. Confirm the key
curl -s https://app.journeystack.co/api/public/v1/ping -H "Authorization: Bearer $JS_KEY" | jq{
"data": {
"ok": true,
"environment": "sandbox",
"partner": "Acme Travel",
"currency": "USD",
"server_time": "2026-01-14T09:30:00.000Z"
}
}2. Find a plan and capture its ID
Plan IDs are account-independent but they are not fixed forever — always read them from the catalogue rather than hard-coding one. This call stores the cheapest unlimited Singapore plan in a shell variable.
PLAN_ID=$(curl -s "https://app.journeystack.co/api/public/v1/plans?country=SG&type=unlimited&limit=1" \
-H "Authorization: Bearer $JS_KEY" | jq -r '.data[0].id')
echo "$PLAN_ID"
# 0f4c1c2e-6f8a-4a09-9f0d-2f1b8c7d5e41Check `validity.billed_per_day` on the plan. When it is true the plan is sold per day and you must send `days` on the order; when it is false the plan has fixed validity and `days` is ignored.
3. Order the eSIM
The `Idempotency-Key` should be something stable from your own system — a booking reference works well. If the call times out you resend the identical request and get the original order back instead of a second purchase.
ORDER=$(curl -s -X POST https://app.journeystack.co/api/public/v1/orders \
-H "Authorization: Bearer $JS_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: BK-90210" \
-d "{
\"plan_id\": \"$PLAN_ID\",
\"quantity\": 1,
\"days\": 7,
\"customer\": { \"name\": \"Ada Lovelace\", \"email\": \"ada@example.com\", \"reference\": \"BK-90210\" }
}")
echo "$ORDER" | jq '.data.status, .data.price, .data.esims[0].id'"completed"
{ "unit": 17.15, "total": 17.15, "currency": "USD" }
"9ac2d51b-8f2e-4d6e-b0a1-6c5f0d9a3b77"4. Deliver the eSIM
The order response already contains everything the traveller needs. You can also fetch it again at any time, which is what you do when someone asks you to resend the QR code.
ESIM_ID=$(echo "$ORDER" | jq -r '.data.esims[0].id')
curl -s https://app.journeystack.co/api/public/v1/esims/$ESIM_ID \
-H "Authorization: Bearer $JS_KEY" | jq '{ qr_code_url, activation_code, smdp_address, status }'{
"qr_code_url": "https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=LPA%3A1%24sandbox.journeystack.co%24A1B2C3D4E5",
"activation_code": "LPA:1$sandbox.journeystack.co$A1B2C3D4E5",
"smdp_address": "sandbox.journeystack.co",
"status": "ALLOCATED"
}Sandbox QR codes do not provide connectivity
5. Check usage and balance
curl -s https://app.journeystack.co/api/public/v1/esims/$ESIM_ID/usage -H "Authorization: Bearer $JS_KEY" | jq
curl -s https://app.journeystack.co/api/public/v1/wallet -H "Authorization: Bearer $JS_KEY" | jqNext
Run the same calls interactively in the sandbox console, then read Purchase and deliver an eSIM for the production-grade version of step 3.