API Authentication & Scopes

Bearer tokens, account binding, the full scope list, role interaction, and how to rotate and revoke safely.

Overview

Every request to the Beeswax API is authenticated with a Bearer token in the Authorization header. Tokens are created in the web app under Account Settings → API Tokens and carry three things: the account they are bound to, the user who created them, and a list of scopes.

Authorization: Bearer YOUR_API_TOKEN

The header is the only supported way to authenticate. Tokens in the query string are not accepted, and there is no cookie or session authentication on the API.


The token

Property Detail
Format 43 characters, URL-safe base64. Treat it as opaque.
Shown Once, immediately after creation. Copy it then.
Bound to One account, permanently.
Acts as The user who created it, with that user's role on the account.
Scopes A fixed list chosen at creation; editable later in the web app.
Expiry Optional date. Expired tokens return 401.
Revocation Immediate. Revoked tokens return 401 but stay listed for audit.
Subscription Tokens stop working (401) while the account's subscription is not active, and resume when it is.
Membership Tokens stop working (401) as soon as their user no longer belongs to the account. Removing a person also revokes their tokens for it, so adding them back later does not revive them.
Last used Recorded on every successful request and shown in the token list.

Who can manage tokens: Owners and Super Admins of the account. Managers, Accountants, Basic users, Contractors and Clients cannot see the API Tokens page. Token management is on every plan, including Free.


Account binding

A token can act on exactly one account, chosen when it is created, and the account is never a request parameter. This is the whole tenancy model:

  • A bookkeeper who looks after six clients creates six tokens, one per account, and names them accordingly.
  • A user who belongs to several accounts can only create a token for an account they are a member of, and the token works only while they remain one. Beeswax refuses to issue anything else.
  • The /accounts endpoint lists the accounts the token's user can see, but the token itself still only reads and writes its own account.

Switching accounts

POST /accounts/switch (requires the all scope) revokes the calling token and returns a fresh token bound to the target account. It exists for first-party clients that log a person in and let them move between accounts. For an integration, create one token per account instead; it is simpler, and a revoked token is a support ticket waiting to happen.

First-party login

POST /sessions exchanges an email and password for an all-scope token. It is reserved for Beeswax's own apps. Do not collect Beeswax passwords in your integration. Ask the account owner for a scoped token instead; it can be revoked without changing anyone's password, and it never grants more than it says on the tin.


Scopes

Scopes are resource:read or resource:write. A :write scope implies the matching :read, and all grants every scope. A request outside the token's scopes returns:

HTTP 403
{ "error": "Insufficient permissions. Required scope: invoices:write" }

Grant the narrowest set that does the job. A reporting sync needs :read scopes only; a system that raises invoices needs invoices:write plus the read scopes it uses to look up clients, accounts and taxes.

Financial

Scope Grants
invoices:read List and view invoices, their lines, postings, files and version history
invoices:write Create, edit, finalise and void invoices; edit sections and lines; attach files; restore versions
expenses:read List and view expenses (bills), their lines, postings, files and versions; the expense inbox
expenses:write Create, edit, finalise and void expenses; attach files; upload documents to the inbox; assign inbox items
quotes:read List and view quotes and their lines
quotes:write Create, edit, finalise and delete quotes; edit sections and lines; attach files
payments:read List and view payments and what each one settles
payments:write Apply a payment to invoices or expenses; remove a payment
transactions:read Read ledger postings under any document, and the per-account ledger
journal_entries:read List and view manual (general) journals
journal_entries:write Create, post and delete draft manual journals
transaction_accounts:read Chart of accounts, default accounts, tax codes, and (with transactions:read) the per-account ledger
reconciliations:read Bank reconciliations (statement checks): periods, rows, processed statement lines, the possible-duplicates report
reconciliations:write Create reconciliations, upload statement PDFs, tick and untick rows, tie statement lines to rows
transaction_templates:read Products & services catalogue
transaction_templates:write Create, update and delete products & services
tax_returns:read Tax returns, field transactions, notes and conversation (Australian accounts)
tax_returns:write Create returns, override fields, add notes, confirm sections, request review, finalise

Contacts, projects and work

Scope Grants
companies:read Clients and suppliers with their contact people
companies:write Create and update clients and suppliers and their people
projects:read Projects and their milestones
projects:write Create and update projects
project_documents:read Project documents and their version history
project_documents:write Create and edit freeform documents; restore versions
tasks:read Tasks, comments and files
tasks:write Create, update, transition and comment on tasks; timers; files
time_entries:read Time entries
time_entries:write Log time
milestones:read Milestones (read only)
events:read Calendar events visible to the token's user (read only)

Account

Scope Grants
users:read Members of the account
accounts:read The accounts the token's user can see
themes:read Document themes and the theme specification
themes:write Create, validate, preview and activate custom document themes
all Everything above, plus POST /accounts/switch and the untyped /journal_entries reader for long-tail types (payrolls, credits, bank transfers)

Endpoints that need no scope

GET /meta and GET /users/me answer any usable token. They reveal only the token holder's own identity, the bound account, the scopes granted and the server clock. Use /meta as your connection check.

Scopes that travel together

Some writes cannot be done without looking things up first:

  • Creating an invoice, quote or expense needs companies:read (to pick the client or supplier), projects:read if you attach it to a project, and transaction_accounts:read (accounts and tax codes for the lines). Add transaction_templates:read to price lines from your catalogue.
  • Recording a payment needs transaction_accounts:read (to find the bank account) and invoices:read or expenses:read (to find what is owed).
  • Reconciling a bank account against its statement needs reconciliations:read to read the statement check and reconciliations:write to tick rows; add transaction_accounts:read and transactions:read for the per-account ledger, and expenses:write or payments:write to record what the statement shows is missing.
  • Posting a manual journal needs transaction_accounts:read for the account ids.

Scopes and roles

Scopes are a ceiling, not a grant. Every request, read or write, is also checked against the creating user's role on the bound account, with the same rules the web app applies. So:

  • A token created by an Accountant with invoices:write can raise invoices, because Accountants can in the app.
  • A token created by a Basic user with invoices:write gets 403 {"error":"Your role does not permit creating or editing invoice documents"}.
  • Reads return what the role sees in the app, no more. A Client's token lists the invoices and quotes of the projects visible to them. A Basic user's token lists the tasks that are theirs and the projects visible to them.
  • A resource the role cannot see at all answers 403, for example {"error":"Your role does not permit reading expenses"} for a Basic user. A single record the role cannot see answers 404, the same as one that does not exist.
  • Plan features apply too. Inbox endpoints on an account whose plan lacks the expenses feature return 403 {"error":"This feature is not available on your current plan."}.

If a token needs to do something its creator cannot, the fix is a token created by an Owner or Super Admin, not a wider scope.


Managing tokens over time

Naming. Name a token after the system and purpose: "Warehouse sync (read)", "Zapier: new invoice → Slack". The list shows the name, masked token, scopes, last used and created dates.

Editing. Name, scopes and expiry can be changed at any time; changes take effect on the next request. The token string itself never changes.

Rotation. There is no in-place rotate. Create the new token, deploy it, confirm the old token's last used stops moving, then revoke the old one. Keep both live during the switch so nothing breaks.

Revoking versus deleting. Revoke when a token may have leaked or a system is decommissioned; the row stays for audit. Delete when you want it gone from the list.

Expiry. Set an expiry on anything temporary: a consultant's access, a migration script, a proof of concept. An expired token fails closed with a 401.

Compromise. If a token is exposed (committed to a repository, pasted in a ticket), revoke it immediately in the web app. Revocation is instant and does not affect other tokens.


Storing tokens in your application

  • Keep tokens server-side in a secrets manager or encrypted configuration. Never ship one in a browser, a mobile app binary, a spreadsheet macro or a shared document.
  • One token per environment (development, staging, production), each bound to the right Beeswax account.
  • Log the token id or name, never the value. Beeswax shows the masked token in the list so you can match logs to tokens.
  • Handle 401 as stop and alert, not retry: the token has been revoked, has expired, the account's subscription has lapsed, or the person it belongs to has left the account. Retrying will not help and the account owner needs to know.
Browse Topics