eliDocs
API Reference

Authentication

How to authenticate requests to the Beliq API using API keys.

Every /v1/ endpoint in this reference requires an API key, except GET /v1/rulesets, which is public. Beliq’s own Playground and free demo call these endpoints with short-lived credentials of their own instead of a key. POST /v1/inbox/:providerId (transmission, preview) is not an endpoint you call: it takes no API key and checks a signature of its own. If a key is missing, the API returns 401 AUTHENTICATION_REQUIRED.

Obtaining an API key

Obtaining an API key

  1. Sign in to the Beliq dashboard
  2. Navigate to Integration → API Keys
  3. Click Create API Key and give it a descriptive label
  4. Copy the key immediately; it is only displayed once

API keys are stored securely in hashed form. Beliq does not store or log your plaintext key.

Passing the API key

Passing the API key

Use one of two methods:

Authorization: Bearer YOUR_API_KEY
import { Beliq } from '@beliq/sdk';

// `auth: 'bearer'` sends Authorization: Bearer instead of the default X-API-Key.
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY!, auth: 'bearer' });
import os

from beliq import Beliq

# auth="bearer" sends Authorization: Bearer instead of the default X-API-Key.
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"], auth="bearer")

X-API-Key header

X-API-Key: YOUR_API_KEY
import { Beliq } from '@beliq/sdk';

// X-API-Key is what the client sends unless you ask for `auth: 'bearer'`.
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
import os

from beliq import Beliq

# X-API-Key is what the client sends unless you ask for auth="bearer".
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

Both methods work the same way. Use whichever is easier in your client.

Example request

Example request

validate.sh
curl -X POST https://api.beliq.eu/v1/validate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/xml" \
  --data-binary @invoice.xml
import { readFile } from 'node:fs/promises';
import { Beliq } from '@beliq/sdk';

const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });

const result = await beliq.validate(await readFile('invoice.xml'));

console.log(result.valid, result.format, result.schematronVersion);
import os
from pathlib import Path

from beliq import Beliq

beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

result = beliq.validate(Path("invoice.xml").read_bytes())

print(result.valid, result.format, result.schematron_version)
Verifying a key

Verifying a key

GET /v1/me returns the account, plan, and live allowance for the calling key. It is a lightweight credential check that does not count against your monthly quota, so it is the right call for “is this key valid?” probes. The official connectors and SDKs use it to validate stored credentials.

me.sh
curl https://api.beliq.eu/v1/me \
  -H "Authorization: Bearer YOUR_API_KEY"
import { Beliq } from '@beliq/sdk';

const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });

// `me()` is the credential check: it does not draw on your monthly quota.
const account = await beliq.me();

console.log(account.livemode, account.plan.name, account.quota.remaining);
import os

from beliq import Beliq

beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

# me() is the credential check: it does not draw on your monthly quota.
account = beliq.me()

print(account.livemode, account.plan.name, account.quota.remaining)
Response
{
  "success": true,
  "data": {
    "keyId": "3f9c2a1b-8e4d-4c7a-9b21-5e0f7d8a6c31",
    "keyPrefix": "blq_live",
    "livemode": true,
    "org": {
      "id": "7b2e9d14-6a03-4f58-8c9e-2d1b4a7f0e63",
      "name": "Acme AG",
      "rulesetChannel": "latest"
    },
    "plan": { "id": 3, "name": "Growth" },
    "rateLimitPerMinute": 200,
    "quota": { "limit": 10000, "used": 1234, "remaining": 8766, "resetsAt": "2026-07-20T09:00:00.000Z" }
  }
}

quota describes the allowance the calling key spends, and livemode says which one that is. On a live key it is your plan quota, and resetsAt is the end of the current window: one month anchored on your billing day, so it falls on the 1st only if your subscription renews on the 1st. On a test key it is the sandbox allowance instead, on the UTC calendar month. Read resetsAt rather than assuming a month boundary. See test mode for what a blq_test_ key reads back.

keyPrefix is the first eight characters of the key, so it reads blq_live or blq_test and carries no key material: only a hash of the key itself is stored. keyId and the org id are UUIDs.

plan.name is never null. An account on the free tier references no plan record, so plan.id is null while plan.name is the free tier’s name. A 401 or 403 here means the key is missing, malformed, or revoked (see the table below).

Error responses

Error responses

HTTP Status Error Code Meaning
401 AUTHENTICATION_REQUIRED No API key was sent
403 INVALID_API_KEY The key that was sent is malformed, does not exist or has been revoked
429 QUOTA_EXCEEDED The monthly quota is used up: your plan’s for a live key, the sandbox allowance for a test key
429 RATE_LIMITED Too many requests in the current rate-limit window; back off and retry
503 DATABASE_UNAVAILABLE Beliq’s database could not serve the request. Any endpoint that takes a key can answer it, GET /v1/me included. Retry after Retry-After
Quotas and rate limits

Quotas and rate limits

Beliq applies request limits to keep the service reliable and fair for all customers.

Throttle Window Source of truth 429 error code
Monthly quota One month anchored on your billing day subscriptionPlans.monthlyQuota (per plan) QUOTA_EXCEEDED
Sandbox allowance (test keys) Calendar month (UTC) Flat, independent of plan QUOTA_EXCEEDED
Per-minute burst Fixed 1-minute window, counted from the first request in it Plan-based rate limit RATE_LIMITED
Abuse throttle Temporary protection window Beliq runtime ACCOUNT_THROTTLED

The two monthly windows do not line up: only an account billed on the 1st sees its plan quota reset when the sandbox allowance does. GET /v1/me reports the boundary that applies to the calling key.

The per-minute window opens with your first request and closes one minute later. Your next request after that opens a new one, so the window does not follow the clock minute. A burst that straddles the end of a window can spend two windows’ allowance back to back.

Quota and rate limits are tracked per account, separately for live and test keys. All live keys of an account share its plan quota and one burst window; all its test keys share the sandbox allowance and a burst window of their own.

Burst and sustained throughput

The per-minute figure is a burst allowance, not a sustained rate: the rate limiter lets the whole minute’s allowance through at once. Your sustained throughput is governed by your monthly quota.

The two are deliberately far apart, so it is worth being concrete: a Business plan allows 300 requests per minute against a quota of 20,000 documents per month. Sending 300 every minute would exhaust the month’s quota in about 67 minutes. Size your integration against the quota, and treat the per-minute figure as headroom for batches and spikes.

How many of those requests run at the same time is bounded separately. Beliq queues what it cannot start immediately, and a queued request answers more slowly, which is normal and not an error. The wait is limited in two ways: a request that has queued for too long, or one that arrives when too many of your account’s requests are already waiting, gets a 503 ENGINE_UNAVAILABLE with Retry-After, and the document’s quota unit is not consumed, so retrying is free. To send a large batch, limit how many requests you have in flight at once, and retry each 503 after Retry-After.

Plan changes mid-window: an upgrade raises the cap on your current window immediately, so the allowance you just paid for is usable the moment the payment lands. A downgrade does not shrink it: the current window keeps the allowance it was billed at, and the smaller one applies from the next window.

QUOTA_EXCEEDED includes your current usage in the message (for example "Monthly quota exceeded (1000/1000)"). Check usage in the dashboard. A plan upgrade raises a live key’s quota; it does not lift a test key’s sandbox allowance.

Response headers

Header Set on Meaning
x-ratelimit-limit /v1/* responses to requests that reached the burst limiter Request limit of the burst window the request counted against: your plan’s for a live key, the sandbox tier’s for a test key, a per-address limit on a route that takes no key
x-ratelimit-remaining /v1/* responses to requests that reached the burst limiter Burst budget left in that window
x-ratelimit-reset /v1/* responses to requests that reached the burst limiter Seconds until that window resets
Retry-After All /v1/* 429 responses Seconds to wait before retrying. For RATE_LIMITED this is the seconds left in the burst window, and the transmission endpoints (preview) have limits of their own; for ACCOUNT_THROTTLED the seconds left in the throttle window, which can be several minutes; for QUOTA_EXCEEDED the seconds until your quota window rolls over (the same instant /v1/me reports as resetsAt), or until the next UTC calendar month for a test-mode key

The three x-ratelimit-* headers come from Beliq’s burst limiter, so only responses to requests that reached it carry them. A request refused before that carries none, for example a 401 or 403 from authentication, an ACCOUNT_THROTTLED 429, a 404 for a path or method that does not exist, or a 400 for a malformed Beliq-Ruleset or Idempotency-Key header.

Always honor Retry-After when present. It indicates the earliest safe retry time.

Prometheus metrics (operators)

When enabled for your deployment, GET /metrics may include a counter beliq_api_http_429_total labeled by throttle subtype (rate_limit_hit, quota_exhausted, abuse_throttle_hit, unknown), and a histogram beliq_api_http_request_duration_seconds (method, route) for request latency, which is useful for alerting and SLO dashboards.

Beliq also sends common browser hardening headers (for example X-Content-Type-Options, X-Frame-Options) on API responses; they do not replace your own security review for embedded contexts.

Default per-minute limits by plan

These are the default per-minute burst allowances by plan, alongside the sustained rate each plan’s monthly quota works out to.

PlanBurst (requests/minute)Monthly quotaSustained average
Free1020under 1/hour
Starter1002,000~3/hour
Growth20010,000~14/hour
Business30020,000~28/hour
Scale50050,000~69/hour

See pricing for what each plan costs.

Test mode uses its own, lower burst allowance. Keys prefixed blq_test_ are limited to 30 requests per minute regardless of plan, with a separate monthly allowance. See test mode.

Key management

Key management

  • Revoke a key at any time from the dashboard. Revoked keys return INVALID_API_KEY immediately.
  • Rotate keys by creating a new key, updating your integration, then revoking the old key.
  • Multiple keys are supported: use separate keys for different environments or services.
  • A membership change can revoke a key too. Removing the member who created a key, or changing their role so they can no longer create keys, revokes it. See team and roles. Keys created before this was tracked record no creator and are not touched.
  • Disabling an account stops the keys of every organization it owns, including keys other members created, because a key acts as its organization’s owner. Re-enabling the account restores them.