Guide
Explorer
no key
Production key active. Mutating requests (POST/PATCH/DELETE) execute live actions and may deduct credits. Sandbox keys (test_*) remain safe for integration testing.

doctorSIM API v2

Integrate mobile top-ups, travel eSIM plans, and digital gift cards for 200+ countries and 1,600+ carriers into your application. This API powers the doctorSIM Agentic Commerce Platform for AI agents and developers.

MCP Server

AI agents can connect via the MCP Server guide using OAuth + PKCE. PRO accounts debit prepaid credits on POST /orders. Regular OAuth users receive a payment_link (hash checkout on doctorsim.com) and get an order_id only after payment.

Order Flows

Every product follows the same spine — find the product → order → monitor — and shares one order history, one credit balance, and one webhook feed (the Core). Only the catalog step differs per vertical. PRO accounts should preview before create (credits are deducted). Consumer OAuth and guests skip preview and receive a payment_link on doctorsim.com (including travel eSIM). Sandbox keys use the sandbox eSIM catalog.

Mobile top-up
1

Lookup phone number

Detect the carrier and country from an E.164 MSISDN before pricing.

GET /topup/carriers/lookup/{phone}
2

Select airtime, data, or bundle

List service types, then pick a rate token for airtime, data, or bundle pricing.

GET /topup/operators/{id}/service-types
GET /topup/operators/{id}/rates
3

Preview price

Confirm the exact breakdown (recharge, service fee, optional SMS fee, total) before placing the order. No credits deducted.

POST /orders/preview
4

Order

Place the top-up with price_token and the recipient phone. PRO: credits deducted instantly. Consumer OAuth: returns payment_link.

POST /orders
Travel eSIM
1

Browse destinations

List countries and regions with published eSIM plans. Pick a country_iso — ISO 3166-1 alpha-2 (es, not ESP), same as top-up country codes and storefront routes. Regional/global destinations use eu, ww, as.

GET /esim/destinations
2

List plans

Load plans for the destination and copy catalog_id and price_token. Pass country_iso as ISO-2 (es) or a region slug (eu, ww, as). Optional data_type=unlimited or limited filters the list. Each plan includes unlimited (boolean).

GET /esim/products?country_iso=es
3

Preview (PRO only)

Required when credits will be deducted. Send catalog_id + price_token (the eSIM token selects the vertical). Confirm retail price. PRO: checkout_mode=credits. Guests skip this step.

POST /orders/preview
4

Order

Same Core create as every vertical. Guest / consumer OAuth: returns payment_link (show this) and order_id when one exists. Buyer types email on /{locale}/esim/checkout/{hash} and receives the eSIM by email — do not display checkout_hash. PRO: credits deducted and order_id returned with type: "esim". Sandbox keys create a fake eSIM (sandbox_esim_{id}, no credit debit, no ticket). (POST /esim/orders is an alias.)

POST /orders
Gift cards
1

Select country

Browse countries with gift card brands and note the country ID or ISO code.

GET /giftcards/countries
2

Search brands

Find the gift card brand, then load its denominations and copy the token.

GET /giftcards/brands?country=
GET /giftcards/brands/{id}/products
3

Preview price

Confirm cost, service fee, and total before checkout. Same body as POST /orders; no order created.

POST /orders/preview
4

Order

Place the gift card order with price_token. Gift cards are delivered digitally — no phone number needed.

POST /orders
Monitor (all verticals)
5

Monitor delivery

Poll order status or register webhooks — the same endpoints for every vertical; the type field tells you which. Fulfilled eSIM orders add iccid, lpa_string, install_url, a hosted PNG qr_code_url, and (detail only) remaining balance_amount with a five-minute provider refresh gate; GET /esim/lines/{iccid} returns the same ICCID-level remaining data. Fulfilled gift cards add redemption_code / redemption_url. Guest / consumer payment-link checkouts (top-up, travel eSIM, gift cards): poll GET /orders?checkout_hash= until order_id is set.

GET /orders/{id}
GET /orders?checkout_hash=
GET /esim/lines/{iccid}
POST /webhooks

Authentication

All protected endpoints accept either API keys or OAuth 2.0 access tokens in the Authorization header.

API keys (server-to-server)

Best for backend integrations and the Explorer above. The Bearer token must contain a colon separating api_id and api_secret:

Authorization: Bearer {api_id}:{api_secret}

Log in to your PRO account, then create keys under My Account → API. The secret is shown only once — store it securely.

OAuth 2.0 (recommended for agents)

Available on this environment. Use dynamic client registration and authorization code + PKCE for interactive agents, or client credentials where supported.

ResourceURL
Authorization server metadatahttps://www.doctorsim.com/.well-known/oauth-authorization-server
Register clientPOST https://www.doctorsim.com/oauth/register
Authorize (PKCE)GET https://www.doctorsim.com/oauth/authorize
Token exchangePOST https://www.doctorsim.com/oauth/token
Agent auth guidehttps://www.doctorsim.com/auth.md

OAuth JWTs use a plain Bearer token (no colon). PRO: scopes include orders:read, orders:write, balance:read, and webhooks. Consumer OAuth: orders:read and orders:write only (no balance or webhooks).

Sign up for a PRO account to get API access and start integrating. See also the Agents landing page.

Environments

Both environments use the same host. The key prefix determines the mode:

EnvironmentKey prefixBehavior
Sandboxtest_*Orders stored in api_sandbox_orders; webhook cron simulates fulfillment (no credits, no Zendesk)
Productionlive_*Live transactions, credits deducted from your balance

Response Format

All responses follow a consistent envelope:

{
  "success": true,
  "data": { ... },
  "meta": {
    "request_id": "req_abc123...",
    "timestamp": "2026-03-24T12:00:00Z"
  }
}

Error responses include an error object with a machine-readable code and human-readable message:

{
  "success": false,
  "data": null,
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credit balance."
  },
  "meta": { ... }
}

Rate Limits

TierRequests/minHeaders
Free50X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Pro500
Enterprise5,000

Endpoint references

Pick the product you are building. Every vertical has its own catalog section; orders, balance, and webhooks are shared (the Core). An eSIM-only integration reads Core + Travel eSIM and can ignore the rest.

Core (all products) Top-up Travel eSIM Gift cards

How the verticals differ

Top-upTravel eSIMGift cards
Catalog/topup/carriers/lookup → /topup/operators/{id}/rates/esim/destinations → /esim/products/giftcards/brands → /giftcards/brands/{id}/products
Product identifierid_operator + rate tokencatalog_id + price_tokenbrand id_operator + rate token
Path prefix/topup/*/esim/*/giftcards/*
Checkout bodyprice_token + phoneprice_token + catalog_idprice_token (no phone)
Who can orderGuest / consumer OAuth (payment_link), PRO (credits)Guest / consumer OAuth (payment_link), PRO (credits)Guest / consumer OAuth (payment_link), PRO (credits)
type valuetopupesimgiftcard
Fulfillment fieldsdelivery_statusiccid, lpa_string, install_url, qr_code_url, balance_amountredemption_code / redemption_url
Unavailable404 ESIM_DISABLED when travel eSIM is not offered on the host

Core — shared by every product

Authentication, orders, balance, and webhooks work the same way for top-up, travel eSIM, and gift cards. The type field (topup, esim, giftcard) tells you which vertical an order belongs to.

Orders

PRO: preview before create (credits are deducted). Guest / consumer: skip preview and create as soon as the product is chosen. Both calls take the same JSON body: the price_token from the vertical catalog plus vertical-specific fields (phone for top-up, catalog_id for eSIM). History and status are shared across verticals; filter history with type.

MethodPathDescription
POST/orders/previewPreview the exact price breakdown (any vertical, no order placed)
POST/ordersCreate an order (any vertical)
GET/orders?type=topup|giftcard|esimList completed orders (any vertical)
GET/orders/{id}Get order status (any vertical)

POST /esim/orders/preview and POST /esim/orders remain as vertical aliases of the two endpoints above (same body, type=esim inferred). New integrations only need /orders/preview and /orders.

Balance

Prepaid credit balance for PRO API keys and OAuth balance:read. One balance funds every vertical.

MethodPathDescription
GET/balanceCheck credit balance. PRO
GET/balance/historyCredit transaction history. PRO

Webhooks

Order event subscriptions for every vertical. Max 5 webhooks per account. The signing secret is shown only once at creation. Events: order.created, order.fulfilled, order.failed; each payload carries the order type.

MethodPathDescription
POST/webhooksRegister a webhook. PRO
GET/webhooksList webhooks. PRO
GET/webhooks/{id}Get webhook detail. PRO
PATCH/webhooks/{id}Update a webhook. PRO
DEL/webhooks/{id}Delete a webhook. PRO

Status & utilities

MethodPathDescription
GET/statusAPI health check. No auth
GET/geoIP geolocation
GET/API v2 root (discovery links). No auth

Top-up

Mobile airtime, bundles, and data for a phone number. Everything lives under /topup/*. Start from the phone number, pick a rate, then use the Core /orders endpoints with price_token + phone.

MethodPathDescription
GET/topup/carriers/lookup/{phone}Identify carrier from phone number
GET/topup/countriesList top-up countries
GET/topup/operatorsList mobile operators
GET/topup/operators/{id}/service-typesGet service types for an operator
GET/topup/operators/{id}/ratesGet pricing and denominations
GET/topup/service-typesList all service type definitions
GET/topup/promotionsGet active promotions
GET/topup/products/searchSearch the top-up catalog
GET/topup/products/{operator_id}Get product detail

The un-prefixed paths (/countries, /operators/*, /products/*, /carriers/*, /service-types, /promotions) keep working as aliases and return the unfiltered catalog (top-up and gift cards together).

Travel eSIM

Prepaid data plans for travellers. Browse a destination, pick a plan, then order — PRO accounts debit credits; consumer OAuth and guests receive a payment_link. Install with the QR / LPA and monitor remaining data by ICCID. Sandbox keys (test_*) use the sandbox catalog and return a fake eSIM (sandbox_esim_{id}, no credit debit); live keys use the production catalog. Confirmation is emailed to the titular account when one is linked.

MethodPathDescription
GET/esim/destinationsList eSIM destinations
GET/esim/productsList eSIM plans
GET/esim/products/{catalog_id}Get eSIM plan detail
POST/esim/orders/previewAlias of POST /orders/preview — same body and response
POST/esim/ordersAlias of POST /orders — same body and response
GET/esim/lines/{iccid}Get eSIM line remaining data
GET/esim/qr/{ticket_id}/{sig}Hosted QR PNG for a fulfilled eSIM order. No auth

Order history and status: Core GET /orders?type=esim and GET /orders/{id}. Everything an eSIM-only integration needs is Core + this section.

Gift cards

Digital gift cards (gaming, streaming, retail) delivered by code or link — no phone number. Everything lives under /giftcards/*; a brand is an id_operator with parent category Giftcard. The Core /orders endpoints deliver them with price_token only.

MethodPathDescription
GET/giftcards/countriesList gift card countries
GET/giftcards/brandsSearch gift card brands
GET/giftcards/brands/{id}/productsGift card denominations for a brand
GET/giftcards/products/{operator_id}Gift card brand detail

Fulfilled gift card orders return redemption_code (PIN) or redemption_url on GET /orders/{id}.

Sandbox vs. Production: Use sandbox keys (test_*) for safe integration testing — orders are stored in api_sandbox_orders and auto-fulfilled via the webhook cron (no credits, no Zendesk). Production keys (live_*) work in the Explorer too; mutating calls show a confirmation because they deduct credits and place real orders.

Select an endpoint

Choose an endpoint from the sidebar to see its parameters, execute it, and view the response. Enter your API credentials in the top bar to make live calls.