Docs
Developer CenterDashboardesimoa.com
    • Introduction
    • Quickstart
    • Authentication
    • Overview
    • List eSIMs
    • Get an eSIM
    • Countries
    • OpenAPI
    • Tracking & commission
    • Rate limits & errors
    • Overview
    • Claude
    • ChatGPT
    • Gemini
    • Other MCP clients
    • Overview
    • Authentication
    • Products
    • Product detail
    • Countries
    • Errors & rate limits
  1. Docs
  2. Partner API (B2B)
  3. Errors & rate limits

Partner API (B2B)

Errors & rate limits

Partner API error codes, per-key rate limits with X-RateLimit headers, and how to retry.

On this page
  • Error format
  • Error codes
  • Rate limits
  • Retrying

Error format#

Error bodies are { statusCode, code, message }. message is human-readable English and may change, so always branch on code.

json
// Success
{ "success": true, "data": ..., "total": 128, "page": 1, "limit": 20 }

// Error
{ "statusCode": 401, "code": "INVALID_API_KEY", "message": "The API key is invalid." }

Note

Query validation errors (400) use the standard format { statusCode: 400, message: [...], error: "Bad Request" } without a code.

Error codes#

HTTPcodeMeaning and fix
401API_KEY_REQUIREDNo key sent — add the X-API-Key header
401INVALID_API_KEYMalformed or unknown key — check the copy was not truncated and that it is not a Public API key
401KEY_REVOKEDRevoked key — issue a new one
401KEY_EXPIREDExpired key (including an old key after the rotation grace period) — use the new key
403PARTNER_SUSPENDEDAccount is not active — contact esimoa
403INSUFFICIENT_SCOPERequest outside the key’s scopes
403IP_NOT_ALLOWEDCalled from an IP outside the allowlist — add your server’s egress IP
404PRODUCT_NOT_FOUNDUnknown or discontinued product
429RATE_LIMITEDRate limit exceeded — retry after Retry-After seconds

Rate limits#

Note

B2B API requests default to 20,000 per hour per key.

The 3,600-second window starts on the first request; the per-minute limit also applies. Quotas count calls, not transferred MB. Operational settings may change the quota.

X-RateLimit-Hour-Limit · X-RateLimit-Hour-Remaining · X-RateLimit-Hour-Reset

These headers report the hourly limit, remaining calls and reset time (Unix seconds). Hourly exhaustion returns HTTP 429 and Retry-After in seconds. Calls rejected by the minute limit do not count toward the hourly quota.

The default is 300 requests per minute per key (per 60-second window, shared across all servers). esimoa can raise it per account under your contract. Every authenticated response carries quota headers.

  • X-RateLimit-Limit — requests allowed per minute
  • X-RateLimit-Remaining — requests left in the current window
  • X-RateLimit-Reset — when the window resets (Unix seconds)
  • Retry-After — on 429, seconds to wait before retrying
http
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1790000000

HTTP/1.1 429 Too Many Requests
Retry-After: 18
{ "statusCode": 429, "code": "RATE_LIMITED", "message": "Rate limit exceeded (300 requests per minute)." }

Retrying#

  • On 429, wait for Retry-After seconds, then retry.
  • Retry 5xx a few times with exponential backoff.
  • 400, 401, 403 and 404 will not change on retry — fix the cause.
  • Caching the catalog for a few minutes keeps you well under the limit.
javascript
async function b2bFetch(url, attempt = 0) {
  const res = await fetch(url, { headers: { 'X-API-Key': process.env.ESIMOA_PARTNER_KEY } });
  if (res.status === 429 && attempt < 3) {
    const wait = Number(res.headers.get('Retry-After') ?? 1);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return b2bFetch(url, attempt + 1);
  }
  const body = await res.json();
  if (!res.ok) throw Object.assign(new Error(body.message), { code: body.code, status: res.status });
  return body;
}

Last updated: October 1, 2026

PreviousCountries

On this page

  • Error format
  • Error codes
  • Rate limits
  • Retrying

APIs and MCP for bringing esimoa eSIMs to your product

Resources

  • Docs
  • API reference
  • Partner API (B2B)
  • MCP server
  • OpenAPI spec

esimoa

  • Home
  • eSIM plans
  • Developer Center
  • Dashboard
  • Partner portal

Company

  • About Us
  • Partnership
  • Terms of Service
  • Privacy Policy
  • Delivery & Refunds Policy

Support

  • support@esimoa.com
  • Support chat

NBase Korea Co., Ltd.

902, Bldg A, 767 Sinsu-ro, Suji-gu, Yongin-si, Gyeonggi-do (Dongcheon-dong, Bundang Suji U-TOWER)

US Headquarters: NBASE CORP. · Corporate Park, Irvine, CA 92606, USA

© 2026 esimoa. All rights reserved.