Travel eSIM
Integrate Travel eSIM products for international data connectivity
Travel eSIM provides prepaid international data connectivity for travelers. This guide walks you through the Travel eSIM integration, from browsing available packages to provisioning and top-ups.
Core Concept
A Travel eSIM consists of two components:
- Subscription: The eSIM container that holds the SIM reference (ICC, MSISDN)
- Data Package (Addon): Contains the actual data allowance, validity period, and supported countries/regions
A subscription always requires at least one data package to be usable. Top-ups are handled by adding additional packages to an existing subscription.
Quick Path
Browse Packages
List available Travel eSIM data packages filtered by country or region.
Create Order
Create an order with both the subscription and initial data package.
Calculate Price
Calculate taxes and totals before payment.
Collect Payment
Collect payment through your own provider or use a managed payment session.
Submit Order
Submit the order to provision the eSIM and activate the data package.
Order Structure
When creating a Travel eSIM order, you need two line items:
- Subscription line item (
TRAVEL_ESIM): Creates the eSIM profile - Addon line item (
TRAVEL_ESIM_PACKAGE): Activates the data package
Order
├── Line Item 1: Subscription (TRAVEL_ESIM)
│ └── Gets ICC, MSISDN from provisioning
│
└── Line Item 2: Addon (TRAVEL_ESIM_PACKAGE)
├── dataGb
├── validityDays
├── countries[] (ISO 3166-1 alpha-2: "ES", "FR")
├── regions[] (EUROPE, AMERICAS, ASIA_PACIFIC, GLOBAL)
└── activationType (INSTANT, FIRST_USE)
Use parentLineItemId to link the addon to a new subscription in the same order. Use
subscriptionId when adding packages to an existing subscription.
1. Browse Available Packages
List Travel eSIM data packages available for purchase. You can filter by country or region to show relevant options to your customers.
# List all Travel eSIM addon packages
curl "https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE" \
-H "X-API-Key: $CONNECT_API_KEY"// List all Travel eSIM addon packages
const response = await fetch(
'https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE',
{
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);
const packages = await response.json();
console.log('Available packages:', packages.items);Filter by Country
# List packages available in Spain
curl "https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE&countries=ES" \
-H "X-API-Key: $CONNECT_API_KEY"// List packages available in Spain
const response = await fetch(
'https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE&countries=ES',
{
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);Filter by Region
# List packages for Europe
curl "https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE®ions=EUROPE" \
-H "X-API-Key: $CONNECT_API_KEY"// List packages for Europe
const response = await fetch(
'https://apiv2.example.com/api/v2/products/offerings?categories=TRAVEL_ESIM_PACKAGE®ions=EUROPE',
{
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);Available regions: EUROPE, AMERICAS, ASIA_PACIFIC, GLOBAL
2. Create Order
Create an order with both the subscription (eSIM container) and the initial data package.
curl -X POST "https://apiv2.example.com/api/v2/orders" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"customerId": "123e4567-e89b-12d3-a456-426614174000"
},
"lineItems": [
{
"type": "SUBSCRIPTION",
"lineItemId": "esim-container",
"productOfferingId": "travel-esim-subscription-offering-id",
"subscriber": {
"name": "John Doe",
"email": "john@example.com"
},
"sim": {
"esim": true
}
},
{
"type": "ADDON",
"lineItemId": "data-package",
"productOfferingId": "europe-5gb-30days-offering-id",
"parentLineItemId": "esim-container"
}
]
}'const order = await fetch('https://apiv2.example.com/api/v2/orders', {
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer: {
customerId: '123e4567-e89b-12d3-a456-426614174000',
},
lineItems: [
{
type: 'SUBSCRIPTION',
lineItemId: 'esim-container',
productOfferingId: 'travel-esim-subscription-offering-id',
subscriber: {
name: 'John Doe',
email: 'john@example.com',
},
sim: {
esim: true,
},
},
{
type: 'ADDON',
lineItemId: 'data-package',
productOfferingId: 'europe-5gb-30days-offering-id',
parentLineItemId: 'esim-container',
},
],
}),
});
const newOrder = await order.json();
console.log('Created order:', newOrder.orderId);Orders with a TRAVEL_ESIM subscription must include at least one TRAVEL_ESIM_PACKAGE line
item. The order will be rejected if no data package is included.
See Create Order
3. Calculate Order Price
Calculate taxes and totals before collecting payment.
curl -X POST "https://apiv2.example.com/api/v2/orders/{orderId}/calculate-price" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json"const priceCalculation = await fetch(
`https://apiv2.example.com/api/v2/orders/${newOrder.orderId}/calculate-price`,
{
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
},
);
const pricedOrder = await priceCalculation.json();
console.log('Order total:', pricedOrder.pricing.total);4. Collect Payment
Travel eSIM orders require prepaid payment before submission. You can collect payment through your own payment provider or use a managed payment session.
Option A: Your Own Payment Provider (Recommended)
Collect payment through your existing payment provider (Stripe, Adyen, Braintree, etc.) and pass the reference when submitting the order. This gives you full control over the checkout experience and lets you use your existing payment infrastructure.
# Step 1: Collect payment through your own provider
# (This happens in your existing payment flow)
# Step 2: Submit the order with the payment reference
curl -X POST "https://apiv2.example.com/api/v2/orders/{orderId}/submit" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalPayment": {
"reference": "pi_3ABC123def456",
"receiptDescription": "Travel eSIM data package",
"receiptUrl": "https://yourapp.com/receipts/abc123"
}
}'// Step 1: Collect payment through your own provider
// (This happens in your existing payment flow)
// Step 2: Submit the order with the payment reference
const submitted = await fetch(
`https://apiv2.example.com/api/v2/orders/${newOrder.orderId}/submit`,
{
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
externalPayment: {
reference: 'pi_3ABC123def456',
receiptDescription: 'Travel eSIM data package',
receiptUrl: 'https://yourapp.com/receipts/abc123',
},
}),
},
);When using external payments, you are responsible for collecting the correct amount and handling refunds through your payment provider.
Option B: Payment Session API
If you prefer a managed payment flow, use the Payment Session API to create a payment session. You can use a hosted checkout page or an embedded payment widget.
curl -X POST "https://apiv2.example.com/api/v2/payment-sessions" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"orderId": "{orderId}",
"paymentProvider": "STRIPE",
"hosted": true,
"returnUrl": "https://yourapp.com/payment/success",
"cancelUrl": "https://yourapp.com/payment/cancel"
}'
# Redirect customer to provider.checkoutUrl from the response for paymentconst paymentSession = await fetch('https://apiv2.example.com/api/v2/payment-sessions', {
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
orderId: newOrder.orderId,
paymentProvider: 'STRIPE',
hosted: true,
returnUrl: 'https://yourapp.com/payment/success',
cancelUrl: 'https://yourapp.com/payment/cancel',
}),
});
const session = await paymentSession.json();
// Redirect customer to session.provider.checkoutUrl for payment5. Submit Order
Submit the order to provision the eSIM and activate the data package. If you used external payment (Option A), the order is already submitted from step 4. If you used a payment session (Option B), submit the order with the payment session ID.
curl -X POST "https://apiv2.example.com/api/v2/orders/{orderId}/submit" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"paymentSessionId": "{paymentSessionId}"
}'
# The created subscription ID is in createdEntities.subscriptions in the responseconst submitted = await fetch(
`https://apiv2.example.com/api/v2/orders/${newOrder.orderId}/submit`,
{
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
paymentSessionId: session.paymentSessionId,
}),
},
);
const submittedOrder = await submitted.json();
console.log('Order state:', submittedOrder.state);
// Get the created subscription
const subscriptionId = submittedOrder.createdEntities.subscriptions[0].subscriptionId;See Submit Order
6. Retrieve eSIM QR Code
After the order is submitted, retrieve the eSIM QR code for the customer to install on their device.
curl "https://apiv2.example.com/api/v2/subscriptions/{subscriptionId}/esim/qrcode" \
-H "X-API-Key: $CONNECT_API_KEY"
# Display the returned QR code to the customer for eSIM installationconst qrCode = await fetch(
`https://apiv2.example.com/api/v2/subscriptions/${subscriptionId}/esim/qrcode`,
{
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);
const qrData = await qrCode.json();
// Display QR code to customer for eSIM installationSee Get eSIM QR Code
Top-Up: Add More Data
When a customer needs more data, create a new order with an addon line item linked to the existing subscription.
curl -X POST "https://apiv2.example.com/api/v2/orders" \
-H "X-API-Key: $CONNECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"customerId": "123e4567-e89b-12d3-a456-426614174000"
},
"lineItems": [
{
"type": "ADDON",
"lineItemId": "topup-package",
"productOfferingId": "europe-10gb-30days-offering-id",
"subscriptionId": "{subscriptionId}"
}
]
}'
# Continue with calculate-price, payment, and submit as aboveconst topupOrder = await fetch('https://apiv2.example.com/api/v2/orders', {
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer: {
customerId: '123e4567-e89b-12d3-a456-426614174000',
},
lineItems: [
{
type: 'ADDON',
lineItemId: 'topup-package',
productOfferingId: 'europe-10gb-30days-offering-id',
subscriptionId: subscriptionId, // Link to existing subscription
},
],
}),
});
// Continue with calculate-price, payment, and submit as aboveMultiple data packages can coexist on one subscription, even covering different regions. Each package has its own validity period and data allowance.
Check Usage
Monitor data consumption for a Travel eSIM subscription.
curl "https://apiv2.example.com/api/v2/subscriptions/{subscriptionId}/usage" \
-H "X-API-Key: $CONNECT_API_KEY"const usage = await fetch(
`https://apiv2.example.com/api/v2/subscriptions/${subscriptionId}/usage`,
{
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);
const usageData = await usage.json();
console.log('Data used:', usageData.dataUsed);
console.log('Data remaining:', usageData.dataRemaining);Subscription States
| State | Description |
|---|---|
PENDING |
Order submitted, awaiting provisioning |
ACTIVE |
eSIM provisioned and ready for use |
CANCELLED |
Subscription terminated |
The subscription stays ACTIVE even when data packages expire. Customers can always add more
packages to continue using the eSIM.
Data Package States
| State | Description |
|---|---|
PENDING |
Package ordered, awaiting activation |
ACTIVE |
Package activated and data available |
EXPIRED |
Validity period ended |
CANCELLED |
Package canceled before expiration |
Activation Types
Data packages support two activation types:
- INSTANT: Package activates immediately upon order submission
- FIRST_USE: Package activates when the customer first connects to the network
Cancel Subscription
To cancel a Travel eSIM subscription:
curl -X POST "https://apiv2.example.com/api/v2/subscriptions/{subscriptionId}/cancel" \
-H "X-API-Key: $CONNECT_API_KEY"const cancelled = await fetch(
`https://apiv2.example.com/api/v2/subscriptions/${subscriptionId}/cancel`,
{
method: 'POST',
headers: {
'X-API-Key': process.env.CONNECT_API_KEY,
},
},
);