Documentation
FRANKLAB API

Authentication

The partner API key, headers, rate limits and safety.

Open .md
Open in AI

Work with an AI assistant

Shares the current documentation without your keys. Long sections are copied in full for you to paste into chat.

Cursor and Claude Code accept short prompts in links. For long sections, ChatGPT and Antigravity, paste the copied documentation manually.

Ask support

Register and get an API key

API access requires an Apergrex account. Register on Apergrex and create your API key in settings. Keep the key private.

Partner API key

Authentication is a partner API key shaped fl_live_<64 hex>. Use it for generation, billing and webhooks. Exception: minting and revoking API keys require the cabinet session; use Settings → API.

Pass it in one of two ways:

bash
# X-API-Key header (recommended)
curl -H "X-API-Key: $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/balance

# Or Authorization: Bearer
curl -H "Authorization: Bearer $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/balance

Response statuses

CodeReasonWhat to do
401Key missing, unknown or deactivatedCheck the key; issue a new one in the cabinet (Settings → API)
403A legacy service key was sentA partner fl_live_ key is required
429Rate limit exceededRetry later; the default is 60 requests/minute per API key

Rate limits

These are default settings, not a throughput guarantee. Billing and webhooks share a bucket: 60 requests/minute per API key, or 60/minute per partner for session requests. A separate per-IP limiter applies to each method (default 100/minute), with these overrides:

MethodPer-IP limit per minute
POST /v1/billing/payment/link3
POST /v1/billing/legal-invoices/create3
POST /v1/billing/legal-invoices/{id}/refresh6
POST /v1/billing/legal-invoices/{id}/sbp-link6
GET /v1/billing/legal-invoices/{id}/pdf12
POST /v1/webhooks/endpoints10
POST /v1/webhooks/endpoints/{id}/rotate-secret10
POST /v1/webhooks/endpoints/{id}/test6
POST /v1/webhooks/deliveries/{id}/replay30

Limits apply together. For 429 follow Retry-After and the retry rules; do not assume generation submissions use the billing limit.

Key permissions (scopes) and lifetime

A key is full-access by default: it opens generation, billing and webhooks. Keys issued earlier are unchanged — they keep working exactly as before and need no action.

A key can be limited to a set of permissions at issue time. The current permission list, and which methods each one opens, is served by the API itself:

bash
# permission reference (cabinet session)
curl -b "franklab_token=$COOKIE" https://apergrex.ru/franklab/api/auth/api-keys/operations
PermissionWhat it opens
usage:readDaily account spend; the n8n credential test
billing:readBalance, tariff, ledger, top-up history
pricing:readPrice catalog and cost estimates (no charge)
tasks:readStatus and results of your own tasks
media:runSubmitting processing and generation (may spend)
webhooks:readReading endpoints and the delivery log
webhooks:manageCreate, rotate secret, test, replay a delivery

Rules worth knowing up front:

  • Permissions can only be narrowed. A limited key can never be returned to full access — issue a new one.
  • Creating payment links is out of reach for every limited key: no permission opens it. Do it from the cabinet session.
  • A limited key can always read its own permissions (GET /v1/billing/api-keys), but sibling keys' permissions are withheld in that response (scopes: null).
  • * is not a permission and is accepted neither by the API nor by the database.

Lifetime is set at issue time (expiresInDays, 1 to 365 days) and there is no default: a key without a lifetime never expires. An expired key answers 401 with code API_KEY_EXPIRED and stays in the cabinet list until you turn on "hide expired". An expired key cannot be extended — issue a new one; PATCH changes only permissions and the label, never the lifetime.

Revocation takes effect on the next request: the key row is re-read on every call and there is no credential cache. A reason can be recorded at revocation (DELETE /auth/api-keys/{id}?reason=...) and is shown in the list.

CodeWhenHTTP
API_KEY_EXPIREDThe key's lifetime has ended401
API_KEY_SCOPE_REQUIREDThe key lacks the permission for this method403
API_KEY_SCOPE_UNKNOWNAn unknown permission was requested (including *)400
API_KEY_SCOPE_EMPTYA limited key was requested with no permissions at all400
API_KEY_SCOPE_DOWNGRADE_FORBIDDENAttempt to return a limited key to full access400
API_KEY_EXPIRY_OUT_OF_RANGELifetime outside 1...365 days400
API_KEY_QUOTA_EXCEEDEDMore than 20 active keys on the account400

Changes to delivery replay responses

POST /v1/webhooks/deliveries/{id}/replay used to answer a single 404 for every refusal. The reasons are now distinguishable:

CodeHTTPReason
DELIVERY_NOT_FOUND404You have no delivery with that id
DELIVERY_NOT_REPLAYABLE409The delivery is in a status a replay cannot start from (for example, already queued)
DELIVERY_ENDPOINT_DELETED409This delivery's endpoint was deleted — there is nowhere to replay to
DELIVERY_ENDPOINT_INACTIVE409This delivery's endpoint is inactive

If your code read every replay failure as "404 — no such delivery", update it: three of the reasons now arrive as 409. The delivery list also gained pagination — GET /v1/webhooks/deliveries?limit=1..100&cursor=... returns {deliveries, nextCursor, shown}.

Key safety

  • The key is stored server-side as a hash only — it cannot be "shown again"; a lost key is revoked and replaced.
  • Send the key over HTTPS only — never in URLs, logs or client-side code.
  • Revoke instantly from your signed-in cabinet session: DELETE /v1/billing/api-keys/{id} (or the Settings → API page). Revocation never needs the key itself — and a key cannot mint a replacement for itself.
  • Use a separate key per integration — labels keep them apart in the list.

Managing keys

Listing your keys is API-key authenticated. Minting and revoking keys requires the cabinet partner session (partner cookie): an API key must not be able to issue further keys, so a compromised key is fully revoked by its own deactivation — it leaves no "children" that would outlive it. This is the same trust model as the Settings → API page.

bash
# list (prefixes only; the raw value is never returned) — API-key auth
curl -H "X-API-Key: $FRANKLAB_KEY" https://apergrex.ru/franklab/api/v1/billing/api-keys

Create (POST /v1/billing/api-keys) and revoke (DELETE /v1/billing/api-keys/{id}) a key from the cabinet: the Settings → API page — or the same request sent from a signed-in cabinet session (the franklab_token cookie).

/en/docs/authentication.md
Need help?Contact support