Authentication & API keys

Base URL and paths

The API is served at the root of the host — no /api path prefix. Use api.esnadapi.com (or https://api-dev.esnadapi.com for develop) and paths like /v1/invoices, /v1/egs. OpenAPI explorer (develop only) is at /docs.

All ZATCA API requests are authenticated with an API key. There is no username/password auth for the API—only the API key.

Getting your API key

Log in to the Esnad dashboard at app.esnadapi.com. In the dashboard, open API Keys and create a new key. The key is shown only once—store it securely. Use it in the Authorization header for every request.

Authorization: Bearer YOUR_API_KEY

Sandbox vs production

When creating an API key in the dashboard, you choose:

  • Sandbox key — prefix zatca_test_. Use for testing and development. All EGS units and invoice submissions using this key go to ZATCA sandbox (developer-portal).
  • Production key — prefix zatca_live_. Use for live ZATCA e-invoicing. All EGS units and submissions using this key go to ZATCA production (Fatoora core).

The key prefix determines the environment. When you submit an invoice, the EGS unit in egs_unit_id must match: sandbox key → sandbox EGS unit only; production key → production EGS unit only. See Flow & integration for diagrams. Prefer the API collection for a ready-to-run sandbox walkthrough.

Dashboard vs API

Dashboard (portal) login uses email + password and returns a JWT for the web app only. That JWT is not used for invoice or EGS API calls. Creating companies, API keys, webhooks, billing, and team settings are dashboard-only — see the Dashboard guide and Multiple companies.

Verify your API key

Use GET /v1/auth/context to confirm your key is valid and see which tenant and environment (sandbox vs production) it belongs to. This is read-only — it does not list or manage keys. Send a User-Agent header from server-side clients (some HTTP libraries omit it by default).

curl -s "https://api.esnadapi.com/v1/auth/context" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "User-Agent: MyApp/1.0"
{
  "tenant_id": "ten_…",
  "tenant_name": "Acme Trading",
  "plan": "business",
  "status": "active",
  "environment": "sandbox",
  "api_key": {
    "id": "apk_…",
    "label": "Production server",
    "prefix": "zatca_test_8b4de",
    "last_used_at": "2026-08-19T12:00:00.000Z",
    "created_at": "2026-08-01T09:00:00.000Z"
  }
}