Authentication
Personal Access Tokens
All new integrations authenticate with a company-specific Personal Access Token, sent in the standard header:
Authorization: Bearer edk_live_<public_id>.<secret>
Properties of a key:
Bound to one company. It cannot reach any other company, whatever the owner’s own access is.
Stored as an HMAC digest. The server never holds the secret, so it cannot be recovered or re-displayed.
Expires after 30, 90, 180 or 365 days, chosen at creation.
Limited by explicit scopes. A request outside the key’s scopes is rejected.
Re-checked on every request against the owner’s current company access. If the owner loses access to the company, the key stops working.
Keys are created, rotated and revoked in the application under API-nycklar. See Getting started.
Scopes
Each route requires exactly one scope. Request the narrowest set that covers your integration.
Scope |
Access |
Covers |
|---|---|---|
|
Read |
Company record and version information. |
|
Read, sensitive |
Bank fields on the company record. Required in addition to
|
|
Read |
Customer invoices. |
|
Write |
Create, update and delete customer invoices. |
|
Read, sensitive |
Supplier register, including contact and bank details. |
|
Read |
SIRI document drafts. |
|
Write |
Create, update and delete SIRI documents. |
|
Read, sensitive |
Fiscal years, chart of accounts, bank and tax account items, and reading verifications. |
|
Write |
Create, update and delete verifications. |
Company list behaviour
GET /user-companies behaves differently depending on how you authenticate.
With a Bearer key, which is bound to one company, it returns a one-element list
containing that company’s full record. With legacy headers it returns every
company the user can reach, as short {company_id, name} entries.
To get the same response either way, address the company directly:
GET /user-companies/{company_id}
Rate limits
Exceeding a limit returns 429 with a Retry-After header (seconds) and
the body {"message": "rate_limited"}. Honour Retry-After rather than
retrying immediately.
Bucket |
Limit |
Counted per |
|---|---|---|
Requests with a Bearer key |
600 per 5 minutes |
Key |
Write requests (POST, PUT, DELETE) |
120 per hour |
Key |
Failed authentication attempts |
100 per 5 minutes |
Client IP |
Requests with legacy credentials |
600 per 5 minutes |
Token |
The write limit is deliberately tight. Batch your work rather than issuing one request per row.
Key rotation
Rotation issues a new secret for an existing key, keeping its name and scopes. You can choose an overlap of 0, 1, 6 or 24 hours during which the old secret still authenticates, so you can deploy the new one without downtime.
Pick zero overlap if you believe the key has leaked.
Revocation takes effect immediately, and a revoked key is never reinstated.
Legacy credentials
Older clients authenticate with a pair of headers:
Access-Token: <token>
Client-Secret: <secret>
These continue to work, but:
Issuance is closed.
POST /edapi/v1/tokensanswers410 Gone. No new pairs are handed out.Do not mix. Sending Bearer and legacy headers in the same request is rejected.
Migrate. Legacy pairs have no scopes and no expiry, which is exactly why they are being retired. Move to a Bearer key with explicit scopes.
Note
Legacy credentials are not bound to a device at request time, and they do not expire on their own. Treat any legacy pair still in production as a standing risk and plan its replacement.