API keys — creation, transport and limits

The key is the only credential for a third party — 40 hex characters shown once and stored as a hash. It has a name, a company, an optional expiry and a per-minute limit. Send it in a header; rotate by creating a new one and deleting the old.

Last updated: 2026-09-21

On this page

No session tokens

A third party has exactly one credential: the API key. No Sanctum tokens, no OAuth — and whatever needs an employee session (the two Dynamics print steps) is not callable from a server.

Creating a key

Settings → Integration → API keys → Add key:

Field Label Rule
name Client name required — “SAP — Finance”
company_id Company required — the company this key writes into; a system serving two companies gets two keys
expires_at Expiry (optional) empty = never expires; a past date is rejected
rate_limit_per_minute Requests / minute 1–100000, default 60

After saving, the key is shown once: “Copy the key now — it won’t be shown again.” Only its SHA-256 hash is stored; there is no retrieval. The key is 40 hex characters (160 random bits).

Columns: ID · Name · Company · Status · Expiry · Requests / minute · Created · Actions. A legacy key without a company shows a No company — disabled badge and a banner with the count; the row’s company editor assigns one (with a confirmation that previously stamped cheques keep their company).

Transport

Three forms, in precedence order — use the first:

# Form Note
1 Header X-API-KEY: <key> use this
2 ?api_key=<key> in the URL leaks into server logs and Referer — avoid
3 secret field in the body redacted from the audit log, but still transmitted

Rejection ladder

The first matching condition ends the request:

# Condition Status Body
1 Integrations disabled 503 {"error":"Integrations are currently disabled"}
2 No key 401 {"error":"Unauthorized"}
3 Key unknown or inactive 401 same text — deliberately indistinguishable
4 Key expired 403 {"error":"API key expired"}
5 Over the limit 429 {"error":"Too many requests","retry_after_seconds":N}

Rate limiting

A fixed 60-second window per key (not per IP). With a limit of 60, requests 1–60 pass and 61 is the first rejected; retry_after_seconds says when to retry. The limit applies after authentication — a wrong key is not rate-limited (see Security).

Rotation and deletion

There is no “revoke” button: deleting a key is final (“systems using it will no longer be able to connect”). Rotation = create a new key → swap it in the external system → delete the old one. Automatic expiry via expires_at. Deleting a key keeps its audit rows, unattributed.

Key scope

A key opens every endpoint (no partial scopes) inside its company: every cheque created with it is stamped with the key’s company; company_id in the payload is optional — if sent and different ⟹ 422 naming both companies. A reference from another company (bank_account_id · cheque_book_id · cheque_leaf_id · partner_id) ⟹ 422. A key without a company ⟹ an explicit 422 until an administrator assigns one. See Security.

اطلب نسختك التجريبية مجانًا