Hubby API (1.3.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/api/bookings" Note: The request path MUST include the "/api" prefix in the signature calculation. For example, if calling "/bookings", use "/api/bookings" in the signature.
  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/api/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/v1_3_0/openapi/
Production server - Use this for live applications
https://api.hubbyesim.com/api/
Staging server - Use this for testing and development
https://api-staging.hubby.dev/api/

Booking

Operations

List all bookings

Request

Retrieves a paginated list of bookings for the authenticated partner. The response is always fresh and not cached (uses Cache-Control headers).

Query
perPageinteger

Number of records to return per page (minimum 1)

Default 10
cursorstring

Cursor for pagination (use nextCursor/prevCursor from previous response)

curl -i -X GET \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings?cursor=string&perPage=10'

Responses

A paginated list of bookings

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Success message"
dataArray of objects(BookingResponse)
paginationobject(PaginationMeta)
Response
application/json
{ "success": true, "message": "Success message", "data": [ {} ], "pagination": { "perPage": 0, "hasNextPage": true, "hasPrevPage": true, "nextCursor": "string", "prevCursor": "string" } }

Create a new booking

Request

Creates a new booking with the specified details. The booking is identified by the email or booking_id parameter. When no package specifications are provided, the end user will be queried for the destination and size will be determined by the partner settings.

Bodyapplication/jsonrequired
departure_datestring(date-time)required

ISO 8601 departure date. Example: '2026-01-03'.

return_datestring(date-time)

ISO 8601 return date. Must be after departure_date. Optional if not provided by the partner.

emailstring(email)

Traveler's email. Required if booking_id is not provided.

booking_idstring>= 3 characters

Booking ID. Required if email is not provided.

external_idstring or null[ 3 .. 100 ] characters

External ID Usable by your organization to further identify the booking (optional).

phonestring^\+\d{1,3}\d{1,14}$

Phone number in E.164 format (e.g., +123456789).

first_namestring[ 1 .. 100 ] characters
last_namestring[ 1 .. 100 ] characters
full_namestring[ 1 .. 200 ] characters
titlestring
Enum"mr.""ms.""mrs.""miss""dr.""prof."
paxinteger>= 1

Number of passengers.

flight_numberstring^[a-zA-Z0-9]{1,10}$
genderstring
Enum"M""F""O"
date_of_birthstring(date-time)

Date of birth in ISO 8601 format.

localestring[ 2 .. 5 ] characters

Locale or language code (e.g., "en", "nl").

dataobject

Additional metadata about the booking.

communication_optionsobject

Optional communication preferences for sending messages. If not provided, messages will not be sent.

package_specificationsArray of objectsnon-emptyrequired

A list of package specifications. At least one entry is required. Each entry is resolved either by package_id (direct reference) or by other properties (destination, size, package_type, etc.); when package_id is present, other fields in that entry are ignored for resolution.

package_specifications[].​destinationstring^[A-Z]{2,3}$

Destination code (ISO 2-3 uppercase letters). Example: 'US', 'NL', 'GRC', 'XA'. (optional)

package_specifications[].​sizestring^[0-9]\d*(\.\d+)?(MB|GB)$

Package size (e.g., '500MB', '1GB', '3GB', '5GB', '10GB', '20GB')

package_specifications[].​package_idstring

Direct package reference. When set, this specification is resolved only by this identifier; other fields in the same specification are not used for resolution and are effectively ignored.

package_specifications[].​package_typestring

Type of package to create.

  • data-limited: Traditional packages with specific data allowance (default)
  • time-limited: Unlimited data for a specific duration
  • starter: Both data and time limited packages
Default "data-limited"
Enum"starter""data-limited""unlimited""time-limited"
package_specifications[].​package_durationinteger>= 1

Duration of the package in days.

  • Defaults to 365 days for data-limited packages
  • Defaults to 2 days for starter and time-limited packages
Default 365
curl -i -X POST \
  https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings \
  -H 'Content-Type: application/json' \
  -d '{
    "departure_date": "2019-08-24T14:15:22Z",
    "return_date": "2019-08-24T14:15:22Z",
    "email": "user@example.com",
    "booking_id": "string",
    "external_id": "string",
    "phone": "string",
    "first_name": "string",
    "last_name": "string",
    "full_name": "string",
    "title": "mr.",
    "pax": 1,
    "flight_number": "string",
    "gender": "M",
    "date_of_birth": "2019-08-24T14:15:22Z",
    "locale": "strin",
    "data": {},
    "communication_options": {
      "should_send_message": true,
      "channels": [
        "EMAIL"
      ]
    },
    "package_specifications": [
      {
        "destination": "string",
        "size": "string",
        "package_id": "string",
        "package_type": "starter",
        "package_duration": 365
      }
    ]
  }'

Responses

Successful response

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Success message"
dataArray of objects(BookingResponse)
Response
application/json
{ "success": true, "message": "Success message", "data": [ {} ] }

Get booking details

Request

Retrieves details of a specific booking

Path
idstringrequired

Booking ID

curl -i -X GET \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings/{id}'

Responses

Successful response

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Success message"
dataobject(BookingResponse)
Response
application/json
{ "success": true, "message": "Success message", "data": { "external_id": "string", "id": "string", "title": "string", "first_name": "string", "last_name": "string", "full_name": "string", "pax": 0, "email": "user@example.com", "phone": "string", "booking_id": "string", "return_date": "2019-08-24T14:15:22Z", "departure_date": "2019-08-24T14:15:22Z", "gender": "M", "locale": "string", "promo_codes": [], "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "created_by": "string", "updated_by": "string" } }

Delete booking

Request

Deletes a specific booking

Path
idstringrequired

Booking ID

curl -i -X DELETE \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings/{id}'

Responses

Successful response

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Success message"
dataobject

Empty object

Example: {}
Response
application/json
{ "success": true, "message": "Success message", "data": {} }

Delete booking by booking ID

Request

Deletes a booking using its external booking ID

Path
idstringrequired

External booking ID (booking_id)

curl -i -X DELETE \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings/{id}/byExternalBookingId'

Responses

Successful response

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Success message"
dataobject

Empty object

Example: {}
Response
application/json
{ "success": true, "message": "Success message", "data": {} }

Update all promo codes for a booking

Request

Updates the package_specification on all promo codes for the booking. Promo codes that have already been used are skipped; the response includes updated_count and skipped_count.

Authentication: HMAC keys.

Path
booking_idstringrequired

The external booking ID (e.g. "BK-12345").

Bodyapplication/jsonrequired
package_specificationobject(PackageSpecification)required

Package specification for updating promo codes. At least one of package_id or package_type must be provided.

When only package_id is sent: The package's properties (package_type, size, package_duration, destination, traffic_policy) are resolved automatically from the referenced package.

When package_id is sent with package_type: The explicit fields from the request body are used instead of the package's own properties.

When only package_type is sent: The conditional field requirements apply based on the type.

Package type requirements:

  • data-limitedsize: required, package_duration: not required, traffic_policy: not applicable
  • time-limitedsize: required, package_duration: required, traffic_policy: not applicable
  • unlimitedsize: not required, package_duration: required, traffic_policy: required
  • startersize: required, package_duration: required, traffic_policy: not applicable
package_specification.​package_idstring

ID of an existing package. At least one of package_id or package_type must be provided.

When package_id is provided without package_type: The package's properties (package_type, size, package_duration, destination, traffic_policy) are resolved automatically from the referenced package.

When package_id is provided with package_type: The explicit fields from the request body are used instead of the package's own properties.

package_specification.​package_typestring

Type of package. At least one of package_id or package_type must be provided.

  • starter: Small data allowance for short duration, ideal for trials
  • data-limited: Traditional packages with specific data allowance
  • unlimited: Unrestricted data usage with fair use policy
  • time-limited: Fixed data allowance with time constraint for full-speed access
Enum"starter""data-limited""unlimited""time-limited"
package_specification.​sizestring^[0-9]\d*(\.\d+)?(MB|GB)$

Package size (e.g. "1GB", "5GB"). Required when package_type is data-limited, time-limited, or starter. Not required for unlimited.

package_specification.​package_durationinteger>= 1

Duration of the package in days. Required when package_type is time-limited, unlimited, or starter. Not required for data-limited.

package_specification.​destinationstring^[A-Z]{2,3}$

Country ISO3 code or IATA code (e.g. "ESP"). Optional — omit for destination-agnostic promo codes.

Example: "ESP"
package_specification.​traffic_policystring

The traffic policy identifier. Required when package_type is unlimited. Not applicable for other package types.

Example: "default_traffic_policy"
curl -i -X PUT \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings/{booking_id}/updatePackageSpecifications' \
  -H 'Content-Type: application/json' \
  -d '{
    "package_specification": {
      "package_id": "string",
      "package_type": "starter",
      "size": "string",
      "package_duration": 1,
      "destination": "ESP",
      "traffic_policy": "default_traffic_policy"
    }
  }'

Responses

Successfully updated package specifications. When some promo codes were skipped (already redeemed), message is "Updated N promo code(s). Skipped M already redeemed." and data includes both updated_count and skipped_count. When all promo codes were updated, message is "Successfully updated package specification for booking." and skipped_count is omitted.

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Updated 3 promo code(s). Skipped 1 already redeemed."
dataobject(UpdatePackageSpecForPromoCodesResponse)
Response
application/json
{ "success": true, "message": "Updated 3 promo code(s). Skipped 1 already redeemed.", "data": { "external_id": "string", "id": "string", "title": "string", "first_name": "string", "last_name": "string", "full_name": "string", "pax": 0, "email": "user@example.com", "phone": "string", "booking_id": "string", "return_date": "2019-08-24T14:15:22Z", "departure_date": "2019-08-24T14:15:22Z", "gender": "M", "locale": "string", "promo_codes": [], "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "created_by": "string", "updated_by": "string", "updated_count": 0, "skipped_count": 0 } }

Update a single promo code by UUID

Request

Updates the package_specification on only the promo code whose uuid matches the path parameter. If that promo code is already redeemed, the API returns 400 Bad Request.

Authentication: HMAC keys.

Path
booking_idstringrequired

The external booking ID.

uuidstring(uuid)required

The promo code's UUID.

Bodyapplication/jsonrequired
package_specificationobject(PackageSpecification)required

Package specification for updating promo codes. At least one of package_id or package_type must be provided.

When only package_id is sent: The package's properties (package_type, size, package_duration, destination, traffic_policy) are resolved automatically from the referenced package.

When package_id is sent with package_type: The explicit fields from the request body are used instead of the package's own properties.

When only package_type is sent: The conditional field requirements apply based on the type.

Package type requirements:

  • data-limitedsize: required, package_duration: not required, traffic_policy: not applicable
  • time-limitedsize: required, package_duration: required, traffic_policy: not applicable
  • unlimitedsize: not required, package_duration: required, traffic_policy: required
  • startersize: required, package_duration: required, traffic_policy: not applicable
package_specification.​package_idstring

ID of an existing package. At least one of package_id or package_type must be provided.

When package_id is provided without package_type: The package's properties (package_type, size, package_duration, destination, traffic_policy) are resolved automatically from the referenced package.

When package_id is provided with package_type: The explicit fields from the request body are used instead of the package's own properties.

package_specification.​package_typestring

Type of package. At least one of package_id or package_type must be provided.

  • starter: Small data allowance for short duration, ideal for trials
  • data-limited: Traditional packages with specific data allowance
  • unlimited: Unrestricted data usage with fair use policy
  • time-limited: Fixed data allowance with time constraint for full-speed access
Enum"starter""data-limited""unlimited""time-limited"
package_specification.​sizestring^[0-9]\d*(\.\d+)?(MB|GB)$

Package size (e.g. "1GB", "5GB"). Required when package_type is data-limited, time-limited, or starter. Not required for unlimited.

package_specification.​package_durationinteger>= 1

Duration of the package in days. Required when package_type is time-limited, unlimited, or starter. Not required for data-limited.

package_specification.​destinationstring^[A-Z]{2,3}$

Country ISO3 code or IATA code (e.g. "ESP"). Optional — omit for destination-agnostic promo codes.

Example: "ESP"
package_specification.​traffic_policystring

The traffic policy identifier. Required when package_type is unlimited. Not applicable for other package types.

Example: "default_traffic_policy"
curl -i -X PUT \
  'https://docs.hubbyesim.com/_mock/apis/v1_3_0/openapi/api/bookings/{booking_id}/updatePackageSpecification/{uuid}' \
  -H 'Content-Type: application/json' \
  -d '{
    "package_specification": {
      "package_id": "string",
      "package_type": "starter",
      "size": "string",
      "package_duration": 1,
      "destination": "ESP",
      "traffic_policy": "default_traffic_policy"
    }
  }'

Responses

Successfully updated the single promo code. updated_count is always 1; there is no skipped_count.

Bodyapplication/json
successboolean
Example: true
messagestring
Example: "Successfully updated package specification for booking."
dataobject(UpdatePackageSpecForPromoCodesResponse)
Response
application/json
{ "success": true, "message": "Successfully updated package specification for booking.", "data": { "external_id": "string", "id": "string", "title": "string", "first_name": "string", "last_name": "string", "full_name": "string", "pax": 0, "email": "user@example.com", "phone": "string", "booking_id": "string", "return_date": "2019-08-24T14:15:22Z", "departure_date": "2019-08-24T14:15:22Z", "gender": "M", "locale": "string", "promo_codes": [], "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "created_by": "string", "updated_by": "string", "updated_count": 0, "skipped_count": 0 } }

Package

Operations

Country

Operations

PromoCode

Operations

eSIM

Operations