Last updated

Hubby Native eSIM Integration

The Native eSIM Integration lets you build a fully custom eSIM experience inside your native mobile app. Your backend communicates with Hubby server-to-server. All telco complexity — eSIM provisioning, package management, universal eSIM lifecycle — is abstracted away. You build the UI and control the payment flow; Hubby provides the data, provisioning engine, and event system.

This page covers the complete flow: every API call in sequence, what you render at each step, installation credentials, AI-powered instructions, and how to monitor usage.

WebView or Native? Most partners start with the Hubby WebView — go live in days with zero frontend work. The Native eSIM Integration is for partners who need full UI control. Both can coexist: start with the WebView and selectively move high-traffic screens (data meter, top-up) to native over time.


What You Build vs. What Hubby Handles

Your teamHubby
All UI screens (installation, data meter, top-up store, package selection)Package provisioning, eSIM assignment, region optimization
Backend calls to Hubby APIUniversal eSIM lifecycle (one eSIM per traveler, packages queue)
Payment processing (you are Merchant of Record)B2B net rate invoicing, B2C price recommendations
Push notifications mapped to webhook eventsWebhook delivery, departure-time CRM triggers
Installation flow using credentials from HubbyAI-powered installation instructions per device/OS
Support UI (Intercom SDK or your own)AI + human support team (< 3 min first response)

Architecture

Hubby APIPartner BackendPartner App(Native UI)Hubby APIPartner BackendPartner App(Native UI)Webhooks push real-time eventsPOST /api/bookingsbooking confirmation + package IDsGET /api/native/user-dashboard?external_user_id=...user + package queues + eSIM + packages + partnerRender UI based on user stateUser taps "Install eSIM"POST /api/native/instructionsDevice-specific installation stepsUser taps "Redeem package"POST /api/native/redeem-packagePackage redeemed + eSIM updatedpackage.usage.80_percentPush notification: "Running low on data"User taps "Buy more data"POST /api/bookings (same external_user_id)New package queued on existing eSIM

The Full Flow

Step 1 — Create a Booking

POST /api/bookings — identical to the WebView flow. Your backend calls this when a traveler qualifies for a package.

curl --request POST \
  'https://api.hubbyesim.com/api/bookings' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1717689600000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE' \
  --header 'Content-Type: application/json' \
  --data '{
    "departure_date": "2026-07-15T14:30:00+02:00",
    "locale": "es",
    "package_specifications": [
      {
        "external_user_id": "partner_user_456",
        "destination": "GR",
        "size": "1GB"
      }
    ]
  }'
{
  "success": true,
  "data": {
    "id": "booking_abc",
    "package_specifications": [
      {
        "external_user_id": "partner_user_456",
        "package_id": "pkg_xyz",
        "destination": "GR",
        "size": "1GB",
        "status": "provisioned"
      }
    ]
  }
}

You specify destination + size (not a package ID). Hubby auto-routes to the optimal package. Multi-destination bookings are automatically optimized — a trip to Greenland, Canada, the US, and Mexico may be fulfilled with a North America regional package plus individual packages.

Important: external_user_id is required for the Native eSIM Integration. It must be your own stable user identifier — the same value is used across all /native/* endpoints (dashboard, redeem, instructions). Do not supply this field if you are not using the Native eSIM Integration or the Hubby WebView — it is ignored in the traditional booking flow and supplying it incorrectly will route the package into the eSIM management flow.


Step 2 — Fetch User Dashboard

GET /api/native/user-dashboard?external_user_id=... — the central endpoint for the Native eSIM Integration. One call returns everything you need to render any screen: user info, pending package queues, current eSIM state, active eSIM packages, and partner details.

curl --request GET \
  'https://api.hubbyesim.com/api/native/user-dashboard?external_user_id=user_abc123' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1711200000000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE'
{
  "success": true,
  "data": {
    "user": {
      "id": "firestore-user-id",
      "external_user_id": "user_abc123",
      "has_universal_esim": true,
      "current_universal_esim": "8901234567890123456"
    },
    "package_queues": [
      {
        "id": "pq_xyz789",
        "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "type": "booking",
        "package_specification": {
          "iso3": "FRA",
          "bytes": 1073741824,
          "duration_days": 30
        },
        "created_at": "2026-03-20T10:00:00.000Z",
        "redeemed_at": null
      }
    ],
    "current_esim": {
      "provider": "esim-provider",
      "name": "Hubby Universal ESIM",
      "qr": "LPA:1$smdp.example.com$ACTIVATION-CODE",
      "iccid": "8901234567890123456",
      "total_data": 1073741824,
      "data_left": 524288000,
      "data_used": false,
      "status": "RELEASED",
      "time_assigned": "2026-03-21T12:00:00.000Z"
    },
    "current_esim_packages": [
      {
        "template": "template-id",
        "destination_bundle": "bundle-id",
        "destination_iso3": "FRA",
        "assigned_at": "2026-03-21T12:00:00.000Z",
        "status": "ACTIVE",
        "total_bytes": 1073741824
      }
    ],
    "partner": {
      "id": "partner-id",
      "name": "Partner Name"
    }
  }
}

What to render based on state

user.has_universal_esimWhat to show
falseNo eSIM yet — waiting for a booking
true (with current_esim)Show eSIM installation flow (Step 3) or data meter depending on eSIM status
current_esim.statusWhat to show
RELEASEDeSIM profile ready — show installation flow (Step 3) using the qr field
INSTALLEDeSIM on device — show package queues or data meter
ENABLEDeSIM active with data — show data meter with data_left / total_data
package_queuesWhat to show
Entries with redeemed_at: null"Redeem" button — use the id field to redeem (Step 5)
No unredeemed entries"Get more data" prompt (Step 7)

When to call

  • Every time the traveler opens the eSIM section in your app
  • After redeeming a package queue (to confirm the updated eSIM state)
  • After a top-up purchase (to confirm the new package queue appeared)
  • Periodically for data meter refresh (or rely on webhooks instead)

Step 3 — eSIM Installation

When current_esim is present and the eSIM status is RELEASED, the traveler needs to install the eSIM. The qr field in current_esim contains the LPA string you need for installation.

Installation Credentials

The current_esim.qr field contains the full LPA string in the format LPA:1$<smdp_address>$<activation_code>. You can parse it or use it directly:

SourceDescription
current_esim.qrFull LPA string — use for QR code generation or programmatic install
current_esim.iccidICCID of the eSIM profile

Platform-Specific Installation

iOS 17.4+ — Use the LPA string from current_esim.qr for programmatic installation via the Carrier Provisioning API. The traveler never leaves your app.

iOS (older versions) — Generate a QR code from the current_esim.qr LPA string. Instruct the traveler to scan it via Settings → Mobile Data → Add eSIM → Use QR Code.

Android — Parse the SM-DP+ address and activation code from the LPA string and use the ACTION_EMBEDDED_SUBSCRIPTION_PROVISIONING intent:

// current_esim.qr = "LPA:1$smdp.example.com$ACTIVATION-CODE"
val parts = lpaString.removePrefix("LPA:1$").split("$")
val intent = Intent(EuiccManager.ACTION_OTA_ESIM_PROVISIONING)
intent.putExtra("server_address", parts[0])
intent.putExtra("matching_id", parts[1])
startActivity(intent)

Tip: Use the installation instructions endpoint (Step 4) instead of hard-coding instructions. It returns device-tailored steps and stays current as OS versions change.


Step 4 — Get Installation Instructions

POST /api/native/instructions — returns AI-generated, device-specific installation instructions tailored to the traveler's exact device model, OS version, and locale. The service automatically resolves the user's eSIM status, activation string, and partner visual identity from the external_user_id, so the returned instructions are fully branded and context-aware.

You do not need to maintain installation content in your app — Hubby keeps it current for every device and OS version.

curl --request POST \
  'https://api.hubbyesim.com/api/native/instructions' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1711200000000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE' \
  --header 'Content-Type: application/json' \
  --data '{
    "format": "html",
    "external_user_id": "user_abc123",
    "device_name": "Google Pixel 10",
    "device_type": "phone",
    "phone_os": "android",
    "os_version": "15",
    "locale": "mk-MK"
  }'

The response shape is dynamic and depends on the requested format. The instructions adapt to:

  • Device model and OS version — different steps for iOS 17.4+ (programmatic) vs older iOS (QR scan) vs Android (intent-based)
  • eSIM state — if already installed, instructions shift to activation/troubleshooting
  • Locale — instructions returned in the requested language
  • Partner branding — visual identity applied to the generated instructions

Step 5 — Check Device Compatibility

Before starting the eSIM flow, you can check whether the traveler's device supports eSIM.

Check a specific device

POST /api/native/device-compatibility — pass the device details and get a compatibility result.

curl --request POST \
  'https://api.hubbyesim.com/api/native/device-compatibility' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1711200000000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE' \
  --header 'Content-Type: application/json' \
  --data '{
    "phone_brand": "Google",
    "phone_model": "Pixel 10"
  }'
{
  "success": true,
  "data": {
    "phone_brand": "Google",
    "phone_model": "Pixel 10",
    "is_compatible": true
  }
}

List all compatible devices

GET /api/native/device-compatibility — returns all known devices and their eSIM compatibility. Use this to build a compatibility page or pre-filter device selection in your app.

curl --request GET \
  'https://api.hubbyesim.com/api/native/device-compatibility' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1711200000000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE'
{
  "success": true,
  "data": {
    "devices": [
      {
        "phone_brand": "Apple",
        "phone_model": "iPhone 15 Pro"
      },
      {
        "phone_brand": "Samsung",
        "phone_model": "Galaxy S24"
      }
    ]
  }
}

Note: The device list is being continuously expanded. The single-device check endpoint is the recommended approach for real-time compatibility verification.


Step 6 — Redeem a Package Queue

POST /api/native/redeem-package — redeems a pending package queue entry, provisioning the package onto the traveler's universal eSIM. Pass the external_user_id and the package_queue_id (the id field from package_queues in the user dashboard response).

curl --request POST \
  'https://api.hubbyesim.com/api/native/redeem-package' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1711200000000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE' \
  --header 'Content-Type: application/json' \
  --data '{
    "external_user_id": "user_abc123",
    "package_queue_id": "pq_xyz789"
  }'
{
  "success": true,
  "message": "Package queue redeemed successfully",
  "data": {
    "package_queue": {
      "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "type": "booking",
      "redeemed_at": null,
      "package_specification": {
        "iso3": "FRA",
        "bytes": 1073741824,
        "duration_days": 30
      }
    },
    "current_esim": {
      "iccid": "8901234567890123456",
      "qr": "LPA:1$smdp.example.com$ACTIVATION-CODE",
      "name": "Hubby Universal ESIM",
      "status": "RELEASED",
      "data_left": 1073741824,
      "total_data": 1073741824,
      "last_updated": "2026-03-23T12:00:00.000Z",
      "time_assigned": "2026-03-23T12:00:00.000Z",
      "esim_type": "classic",
      "provider": "esim-provider"
    },
    "current_esim_packages": [
      {
        "allowance_seconds": 2592000,
        "allowance_hours": 720,
        "allowance_days": 30,
        "assigned_at": "2026-03-23T12:00:00.000Z",
        "date_activated": null,
        "status": "ACTIVE",
        "total_bytes": 1073741824,
        "type": "data"
      }
    ]
  }
}

The response returns the redeemed package queue entry along with the updated eSIM state and current packages, so you can immediately update the UI without an extra dashboard call.


Step 7 — Top-Up

To add more data, create another booking with the same external_user_id. The new package is automatically queued onto the traveler's existing eSIM — no re-installation needed.

curl --request POST \
  'https://api.hubbyesim.com/api/bookings' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1717689600000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE' \
  --header 'Content-Type: application/json' \
  --data '{
    "departure_date": "2026-07-20",
    "package_specifications": [
      {
        "external_user_id": "partner_user_456",
        "destination": "GR",
        "size": "3GB"
      }
    ]
  }'

This is the same booking endpoint as Step 1. The Universal eSIM architecture means every new package for the same external_user_id is added to their existing eSIM — one installation, unlimited top-ups.


Step 8 — Monitor Usage

Two approaches, use both:

Pull: User dashboard endpoint — call GET /api/native/user-dashboard?external_user_id=... to refresh the data meter. The current_esim object includes data_left and total_data, and current_esim_packages lists each package with total_bytes and status.

Push: Webhooks — receive real-time events at 20%, 50%, and 80% data usage thresholds. Map these to push notifications. See the webhooks guide for the full event catalog.

EventSuggested action
package.usage.50_percent"You've used half your data in Greece" (or "Your package is halfway through")
package.usage.80_percent"Running low — top up now to stay connected" (or "Your package expires in 6 days")
booking.within_cutoff (eSIM not installed)"Your trip is in 7 days — install your eSIM now"
booking.about_to_depart (eSIM not installed)"Departing in 2 hours — install before you board"

Step 9 — Payments

In the Native eSIM Integration model, you are the Merchant of Record. Hubby never touches payments. You handle the payment flow in your app using your own PSP, then call the booking endpoint to provision the package.

  • Hubby provides B2B net rates and recommended B2C prices in the package catalog (GET /destinations/{id})
  • You set your own retail prices or use Hubby's B2C recommendations (continuously updated based on market rates)
  • Hubby invoices you monthly at B2B net rates

Package Catalog

The Hubby API is organized around Destinations and Bundles — the same concepts your travel platform already uses. A Destination is a country or region; each Destination has one or more Bundles (data products with different sizes, durations, and prices). Use the destination endpoints to build your package selection UI:

GET /api/destinations — all available destinations (countries and regions) with localized names, ISO3 codes, and metadata.

curl --request GET \
  'https://api.hubbyesim.com/api/destinations' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1717689600000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE'

GET /api/destinations/{id} — a single destination with its available bundles (data packages) including B2B and B2C prices.

curl --request GET \
  'https://api.hubbyesim.com/api/destinations/GR' \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'x-timestamp: 1717689600000' \
  --header 'x-signature: YOUR_HMAC_SIGNATURE'

Support Integration

For Native eSIM Integration partners, support is integrated via the Intercom SDK:

  1. Embed the Intercom SDK in your iOS and Android app
  2. When opening a support session, populate user context fields:
    • external_user_id, device_model, os, os_version
    • booking_destination, departure_date
    • package_status, esim_status
  3. Hubby's support team (AI + human) receives this context automatically
  4. First response time: < 3 minutes

Escalation paths:

  • Direct: Traveler → Hubby AI → Hubby human agent
  • Via partner: Traveler → your support team → escalation to Hubby via dedicated channel

Platform Guarantees

MetricCommitment
API uptime99.99% (Google Cloud SLA)
Provisioning success rate99.9%
Support first response (human)< 3 minutes
Webhook deliveryBest-effort, near-real-time
Data usage reporting delay~15 minutes (industry-wide telco limitation)
Backward compatibility4+ years without breaking changes
Rate limitingNone (elastic serverless infrastructure)

Key Advantages Over Other eSIM APIs

Package Specs, Not Package IDs

You specify destination + size. Hubby auto-routes to the optimal package. No catalog sync, no stale IDs, no manual mapping.

Universal eSIM

One eSIM per traveler, installed once. Every subsequent package queues onto the same eSIM. Multi-destination trips, top-ups, returning travelers — all on one installation.

Zero Telco Exposure

Your integration never sees ICCIDs, MCC/MNC codes, or carrier-specific provisioning flows. Hubby abstracts all telco complexity behind clean REST endpoints.

AI-Powered Installation Instructions

Device-specific, OS-aware, locale-aware installation steps generated on the fly. No hard-coded content to maintain in your app.

HMAC Authentication

Simpler than OAuth2 — no token lifecycle, no refresh flows. One HMAC signature per request using your secret key. See the authentication guide.

Travel-Aware Webhooks

Departure-time triggers (booking.within_cutoff, booking.about_to_depart) that no generic eSIM API offers. Built for travel, not just connectivity.


Quick-Start Checklist

Your team provides:

  • external_user_id format (your internal user ID)
  • Package selection UI designs
  • Payment flow (your PSP)
  • Push notification mapping for webhook events
  • Installation UI (or use Hubby's instructions endpoint)
  • Technical point of contact

Hubby provides:

  • API keys (staging + production)
  • Staging environment with all endpoints
  • Package catalog with B2B + B2C prices
  • AI-powered installation instructions
  • Intercom SDK configuration for support
  • Integration support throughout the process