Hubby API (2.0.0)

Welcome to the Hubby API documentation. This API enables partners to seamlessly integrate eSIM booking and management capabilities into their applications.

Key Features:

  • Create and manage eSIM bookings for your customers
  • Access our global package catalog with country-specific offerings
  • Track booking statuses and package activations
  • Support for multiple package types (starter, data-limited, unlimited, time-limited)

Package Types

The API supports four types of packages:

  • Starter packages: Hybrid packages that are both data and time limited. They provide a small data allowance within a short time period (default: 2 days). Perfect for first-time users and trials.

  • Data-limited packages: Traditional packages with a specific data allowance that expires after a certain period (default: 365 days). This is the primary package type and the default for most use cases.

  • Unlimited packages: Packages that provide unrestricted data usage for a specified duration. Subject to fair use policy. Ideal for heavy data users and digital nomads.

  • Time-limited packages: Packages that provide a fixed data allowance for a specific duration with full-speed access. These packages expire when either the data limit or time limit is reached.

Note: Top-ups are always data-limited packages, regardless of the original package type.

Authentication: All API requests must include the following headers:

  • x-api-key: Your public API key
  • x-timestamp: Current Unix timestamp in milliseconds
  • x-signature: HMAC-SHA256 signature

The HMAC signature must be generated for each request using:

  1. Concatenate: timestamp + HTTP method + request path Example: "1678901234GET/bookings"
  2. Generate HMAC-SHA256 using your secret key
  3. Convert to hex string

Note: Swagger UI cannot be used to test the API directly as each request requires a unique HMAC signature. Please implement the authentication in your client application.

Example Node.js Implementation:

const cryptoJs = require('crypto-js');

// Configuration values that would normally come from environment
const secretKey = "YOUR_API_SECRET";
const publicKey = "YOUR_API_KEY";
const baseUrl = "YOUR_BASE_URL";

// Function to generate headers for API request
function generateApiHeaders(method, path) {
    //Timestamp is in milliseconds e.g. 1715558400000
    const timestamp = Math.floor(Date.now()).toString();

    // Ensure url is a string
    let path = String(url);

    // Remove baseUrl from the url if present
    path = processedUrl.replace(baseUrl, '');

    // Create query string if needed
    const queryString = new URL(url).search;
    if (queryString) {
        processedUrl += queryString;
    }

    // Validate public key
    if (!publicKey) {
        throw new Error("Public key is required");
    }

    // Create the payload
    // Sample payload: 1715558400000GET/bookings?bookingId=1234567890
    const payload = timestamp + method + path;

    // Generate the HMAC signature
    const signature = cryptoJs.HmacSHA256(payload, secretKey).toString(cryptoJs.enc.Hex);

    // Return headers object
    return {
        'x-timestamp': timestamp,
        'x-signature': signature,
        'x-api-key': publicKey,
        'Accept': 'application/json'
    };
}

Need Help?

  • Technical Support: support@hubbyesim.com
Download OpenAPI description
Languages
Servers
Mock server
https://docs.hubbyesim.com/_mock/apis/v2_0_0/openapi/
Production server
https://europe-west4-hubby-esim.cloudfunctions.net/api_v2/

Booking

Operations

Package

Operations

Country

Operations

PromoCode

Operations

eSIM

Operations

WebView

Operations

Native API

Operations

Webhooks

Webhooks

package.usage.20_percentWebhook

Request

Triggered per package when 20% of the package's data has been consumed (data-limited) or 20% of the package's duration has elapsed (time-limited).

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "package.usage.20_percent"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Per-package usage event data. These events are emitted per package, not per eSIM. For data-limited packages, thresholds are based on data consumption. For time-limited packages, thresholds are based on duration elapsed.

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​package_idstring

The specific package that triggered the event

Example: "pkg_xyz"
data.​destinationstring

ISO country code

Example: "GR"
data.​sizestring

Package size (data-limited packages only)

Example: "1GB"
data.​package_typestring

Type of package

Enum"data-limited""time-limited""unlimited""starter"
Example: "data-limited"
data.​used_bytesinteger

Bytes consumed so far (data-limited packages)

Example: 858993459
data.​remaining_bytesinteger

Bytes remaining (data-limited packages)

Example: 214748365
data.​duration_daysinteger

Total package validity in days (time-limited packages)

Example: 30
data.​elapsed_daysinteger

Days elapsed since activation (time-limited packages)

Example: 24
data.​remaining_daysinteger

Days remaining (time-limited packages)

Example: 6
data.​usage_percentinteger

Usage percentage that triggered this event (20, 50, or 80). Represents data consumed (data-limited) or duration elapsed (time-limited).

Example: 80
application/json
{ "event": "package.usage.20_percent", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "package_id": "pkg_xyz", "destination": "GR", "size": "1GB", "package_type": "data-limited", "used_bytes": 858993459, "remaining_bytes": 214748365, "duration_days": 30, "elapsed_days": 24, "remaining_days": 6, "usage_percent": 80 } }

Responses

Webhook received successfully

package.usage.50_percentWebhook

Request

Triggered per package when 50% of the package's data has been consumed (data-limited) or 50% of the package's duration has elapsed (time-limited).

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "package.usage.50_percent"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Per-package usage event data. These events are emitted per package, not per eSIM. For data-limited packages, thresholds are based on data consumption. For time-limited packages, thresholds are based on duration elapsed.

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​package_idstring

The specific package that triggered the event

Example: "pkg_xyz"
data.​destinationstring

ISO country code

Example: "GR"
data.​sizestring

Package size (data-limited packages only)

Example: "1GB"
data.​package_typestring

Type of package

Enum"data-limited""time-limited""unlimited""starter"
Example: "data-limited"
data.​used_bytesinteger

Bytes consumed so far (data-limited packages)

Example: 858993459
data.​remaining_bytesinteger

Bytes remaining (data-limited packages)

Example: 214748365
data.​duration_daysinteger

Total package validity in days (time-limited packages)

Example: 30
data.​elapsed_daysinteger

Days elapsed since activation (time-limited packages)

Example: 24
data.​remaining_daysinteger

Days remaining (time-limited packages)

Example: 6
data.​usage_percentinteger

Usage percentage that triggered this event (20, 50, or 80). Represents data consumed (data-limited) or duration elapsed (time-limited).

Example: 80
application/json
{ "event": "package.usage.50_percent", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "package_id": "pkg_xyz", "destination": "GR", "size": "1GB", "package_type": "data-limited", "used_bytes": 858993459, "remaining_bytes": 214748365, "duration_days": 30, "elapsed_days": 24, "remaining_days": 6, "usage_percent": 80 } }

Responses

Webhook received successfully

package.usage.80_percentWebhook

Request

Triggered per package when 80% of the package's data has been consumed (data-limited) or 80% of the package's duration has elapsed (time-limited). This is the most effective trigger for top-up conversion.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "package.usage.80_percent"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Per-package usage event data. These events are emitted per package, not per eSIM. For data-limited packages, thresholds are based on data consumption. For time-limited packages, thresholds are based on duration elapsed.

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​package_idstring

The specific package that triggered the event

Example: "pkg_xyz"
data.​destinationstring

ISO country code

Example: "GR"
data.​sizestring

Package size (data-limited packages only)

Example: "1GB"
data.​package_typestring

Type of package

Enum"data-limited""time-limited""unlimited""starter"
Example: "data-limited"
data.​used_bytesinteger

Bytes consumed so far (data-limited packages)

Example: 858993459
data.​remaining_bytesinteger

Bytes remaining (data-limited packages)

Example: 214748365
data.​duration_daysinteger

Total package validity in days (time-limited packages)

Example: 30
data.​elapsed_daysinteger

Days elapsed since activation (time-limited packages)

Example: 24
data.​remaining_daysinteger

Days remaining (time-limited packages)

Example: 6
data.​usage_percentinteger

Usage percentage that triggered this event (20, 50, or 80). Represents data consumed (data-limited) or duration elapsed (time-limited).

Example: 80
application/json
{ "event": "package.usage.80_percent", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "package_id": "pkg_xyz", "destination": "GR", "size": "1GB", "package_type": "data-limited", "used_bytes": 858993459, "remaining_bytes": 214748365, "duration_days": 30, "elapsed_days": 24, "remaining_days": 6, "usage_percent": 80 } }

Responses

Webhook received successfully

esim.installedWebhook

Request

Triggered when the traveler has successfully installed the eSIM on their device.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "esim.installed"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​iccidstring

ICCID of the eSIM

Example: "8901234567890123456"
application/json
{ "event": "esim.installed", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "iccid": "8901234567890123456" } }

Responses

Webhook received successfully

esim.removedWebhook

Request

Triggered when the traveler has removed the eSIM from their device. A removed eSIM can be re-installed — this event does not mean permanent loss of access.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "esim.removed"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​iccidstring

ICCID of the eSIM

Example: "8901234567890123456"
application/json
{ "event": "esim.removed", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "iccid": "8901234567890123456" } }

Responses

Webhook received successfully

package.activatedWebhook

Request

Triggered when a package has been activated and the traveler can use data. Typically occurs when the traveler arrives at the destination and connects to a local network.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "package.activated"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​package_idstring

Package ID

Example: "pkg_xyz"
data.​destinationstring

ISO country code

Example: "GR"
data.​sizestring

Package size

Example: "1GB"
data.​activated_atstring(date-time)

When the package was activated

Example: "2026-07-15T16:00:00Z"
data.​expires_atstring(date-time)

When the package expires

Example: "2027-07-15T16:00:00Z"
application/json
{ "event": "package.activated", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "package_id": "pkg_xyz", "destination": "GR", "size": "1GB", "activated_at": "2026-07-15T16:00:00Z", "expires_at": "2027-07-15T16:00:00Z" } }

Responses

Webhook received successfully

promo_code.redeemedWebhook

Request

Triggered when a traveler successfully redeems a promo code.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "promo_code.redeemed"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​promocodestring

The promo code that was redeemed

Example: "SUMMER2026GR"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​redeemed_atstring(date-time)

When the promo code was redeemed

Example: "2026-07-10T12:00:00Z"
application/json
{ "event": "promo_code.redeemed", "timestamp": "2019-08-24T14:15:22Z", "data": { "promocode": "SUMMER2026GR", "booking_id": "booking_abc", "redeemed_at": "2026-07-10T12:00:00Z" } }

Responses

Webhook received successfully

booking.within_cutoffWebhook

Request

Triggered when the booking's departure date enters the configured cutoff window (default: 7 days). This is the optimal time for travelers to install their eSIM while still at home on Wi-Fi. The esim_installed field indicates whether the traveler has already installed — use it to decide whether to send an installation reminder or a confirmation.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "booking.within_cutoff"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​departure_datestring(date-time)

ISO 8601 departure datetime with timezone

Example: "2026-07-15T14:30:00+02:00"
data.​days_until_departureinteger

Days remaining until departure

Example: 7
data.​esim_installedboolean

Whether the traveler has installed their eSIM

Example: false
application/json
{ "event": "booking.within_cutoff", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "departure_date": "2026-07-15T14:30:00+02:00", "days_until_departure": 7, "esim_installed": false } }

Responses

Webhook received successfully

booking.about_to_departWebhook

Request

Triggered when departure is imminent (default: 2 hours before the time in departure_date). This is the last-chance reminder for travelers who haven't installed their eSIM. Requires a full datetime with timezone in departure_date (e.g., 2026-07-15T14:30:00+02:00) — if only a date string was provided, this event cannot fire.

Bodyapplication/json
eventstringrequired

Event type identifier

Example: "booking.about_to_depart"
timestampstring(date-time)required

ISO 8601 UTC timestamp of when the event occurred

dataobjectrequired

Event-specific payload

data.​external_user_idstring

Partner's own user identifier

Example: "partner_user_456"
data.​booking_idstring

Booking ID

Example: "booking_abc"
data.​departure_datestring(date-time)

ISO 8601 departure datetime with timezone

Example: "2026-07-15T14:30:00+02:00"
data.​hours_until_departureinteger

Hours remaining until departure

Example: 2
data.​esim_installedboolean

Whether the traveler has installed their eSIM

Example: false
application/json
{ "event": "booking.about_to_depart", "timestamp": "2019-08-24T14:15:22Z", "data": { "external_user_id": "partner_user_456", "booking_id": "booking_abc", "departure_date": "2026-07-15T14:30:00+02:00", "hours_until_departure": 2, "esim_installed": false } }

Responses

Webhook received successfully