Skip to main content
All endpoints use HMAC-SHA256 signature-based authentication.

Required Headers

All requests must include the following headers:
  • X-Esim-Story-Access-Key: Your partner access key
  • X-Esim-Story-Signature: HMAC-SHA256 signature of the request
  • X-Esim-Story-Timestamp: Unix timestamp in seconds (UTC)

Signature Generation

The signature is generated using HMAC-SHA256 with your Base64-encoded secret key. Follow these steps:
  1. Decode your secret key from Base64
  2. Construct the raw string using newline characters (\n):
    {HTTP_METHOD}\n{REQUEST_PATH}\n{TIMESTAMP}\n{ACCESS_KEY}
    
  3. Generate HMAC-SHA256 signature using the decoded secret key
  4. Convert to hexadecimal string (lowercase)
Important Notes:
  • Use the exact HTTP method in uppercase (e.g., POST, GET)
  • Use the exact request path (e.g., /api/v1/api_partner/orders) - do not include query parameters or domain
  • Timestamp must be Unix timestamp in seconds (not milliseconds)
  • All components must be joined with newline characters (\n)

Example

#!/bin/bash

# Configuration
ACCESS_KEY="your_access_key"
SECRET_KEY="your_base64_encoded_secret_key"

# Generate timestamp (Unix seconds)
TIMESTAMP=$(date +%s)

# Request details
METHOD="POST"
PATH="/api/v1/api_partner/orders"

# Construct raw string
RAW_STRING="${METHOD}\n${PATH}\n${TIMESTAMP}\n${ACCESS_KEY}"

# Decode secret key and generate signature
DECODED_SECRET=$(echo -n "$SECRET_KEY" | base64 -d)
SIGNATURE=$(echo -n -e "$RAW_STRING" | openssl dgst -sha256 -hmac "$DECODED_SECRET" | cut -d' ' -f2)

# Make request
curl -X POST https://api.esimstory.com/api/v1/api_partner/orders \
  -H "Content-Type: application/json" \
  -H "X-Esim-Story-Access-Key: ${ACCESS_KEY}" \
  -H "X-Esim-Story-Signature: ${SIGNATURE}" \
  -H "X-Esim-Story-Timestamp: ${TIMESTAMP}" \
  -d '{
    "external_order_id": "1234567890",
    "products": [
      {
        "option_id": "686ffd73-61af-ee11-be9e-002248f7dbdd",
        "qty": 1
      }
    ]
  }'

Authentication Flow

The authentication process follows these steps:
  1. Extract headers - Server reads X-Esim-Story-Access-Key, X-Esim-Story-Signature, and X-Esim-Story-Timestamp
  2. Validate headers - All three headers must be present
  3. Validate timestamp - Timestamp must be within 5 minutes of current UTC time
  4. Find partner - Look up partner by access key
  5. Verify secret key - Ensure partner has a valid secret key
  6. Generate expected signature - Recreate signature using the same algorithm
  7. Compare signatures - Use constant-time comparison to prevent timing attacks

Security Requirements

  • Timestamp Validation: The timestamp must be within 5 minutes of the current UTC time to prevent replay attacks
  • Secret Key: Your secret key is stored Base64-encoded and must be decoded before use in signature generation
  • Path: Use the exact request path (e.g., /api/v1/api_partner/orders) - do not include:
    • Query parameters
    • Domain name
    • Protocol
  • Method: Use the exact HTTP method in uppercase (e.g., POST, GET)
  • Newline Characters: The raw string must use actual newline characters (\n), not literal \n strings

Error Responses

If authentication fails, you’ll receive a 401 Unauthorized response:
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid signature."
  }
}
Error Messages:
  • "Missing required authentication headers." - One or more required headers (X-Esim-Story-Access-Key, X-Esim-Story-Signature, X-Esim-Story-Timestamp) are missing
  • "Request timestamp is too old or invalid." - Timestamp is outside the 5-minute window or invalid format
  • "Invalid or missing access key. Please provide a valid X-Esim-Story-Access-Key header." - Access key is incorrect or partner not found
  • "Missing secret key in partner record." - Partner exists but has no secret key configured
  • "Invalid signature." - Signature verification failed (most common cause: incorrect raw string construction or secret key)
Last modified on January 29, 2026