Using the API
Authentication
Authenticate with API keys, web app sessions or MCP tokens. Scopes, draft-only and auto-send modes, account selection and fresh sign-in.
Every call to https://api.freeinvoiceautomation.com/v1 runs as someone: a person signed in to the web app, an API key, an MCP client or a public link. The API works out who that is, which account and businesses they can reach, and which permission keys they hold, before it does anything else.
For your own scripts and servers, use an API key. The other methods are listed below so you know how the rest of the product signs in.
Methods at a glance
| Method | Used by | How it is sent |
|---|---|---|
| API key | your code, the CLI, the Shopify app, the WordPress plugin | Authorization: Bearer <key> |
| Session | the web app at app.freeinvoiceautomation.com | a secure, HttpOnly cookie, with a CSRF token on writes |
| MCP OAuth token | Claude, ChatGPT, Grok, Gemini and other MCP clients | issued after you sign in and approve on a consent screen |
| Client scope | the pay page, estimate page and client portal | a public token in the link |
| None | generate_pdf, document verification, the waitlist, pay-page reads | no credentials, limited per IP address |
API keys
Create a key
Open Settings > API keys
Sign in to the web app and open Settings > API keys. You need the integrations.manage permission, which Owners and Admins have by default.
Name the key and choose its scopes
Give the key a name that says where it is used, such as "Billing server". Tick only the scopes it needs. Scopes are permission keys, for example documents.create and clients.view. You can only tick keys that you hold yourself.
Choose the mode
Leave the mode on draft only unless the key must send documents to clients without a person confirming. Creating an auto_send key asks you to sign in again.
Copy the key
The full key is shown once. Store it in your secret manager or environment. We keep only a hash, so we cannot show it again; if you lose it, revoke it and create a new one.
You can do the same through the API with Create an API key, list keys with List API keys and revoke one with Revoke an API key.
Use a key
Send the key as a bearer token on every request:
curl "https://api.freeinvoiceautomation.com/v1/documents?status=sent,overdue" \
-H "Authorization: Bearer $FIA_API_KEY"Keys start with the prefix fia_ (proposed), so secret scanners such as GitHub's can find a key that was committed by mistake. The first characters of each key are shown in Settings > API keys so you can tell keys apart.
What a key carries
- One account. A key is bound to the account it was created in. It cannot reach other accounts, even if you are a member of them.
- Scopes. The list of permission keys it may use. A call that needs a key the scopes do not include fails with
scope_missing(403). - Mode.
draft_only(the default) orauto_send. See Draft-only and auto-send. - Business restriction (proposed). A key can be limited to some of the account's businesses. Calls about any other business fail with
business_out_of_scope. - A rate limit. Each key has its own per-minute limit. See Rate limits.
- Optional expiry. A key can have an expiry date, after which it stops working.
- Last used. The app shows when each key was last used, so you can spot keys nobody needs any more.
A key never exceeds its creator
At call time a key is limited to the intersection of its scopes and the current permissions of the person who created it. If that person's role loses a permission, the key loses it on the next request. If the person is deactivated or removed from the account, their keys are revoked and return unauthenticated.
Reactivating a member does not bring their old keys back. They create new keys after reactivation. The same happens after a Team account drops to Free and the Owner later reactivates members.
Draft-only and auto-send
The mode decides what happens when the key asks to send something to a client.
| Mode | send_document and other sends | Destructive actions |
|---|---|---|
draft_only (default) | Need "confirm": true in the body; without it you get the preview and confirmation_required | Always need "confirm": true |
auto_send | Run without confirm | Always need "confirm": true |
An auto_send key can email your clients with no person in the loop, so creating one requires a fresh sign-in, and keys with auto_send should be reviewed from time to time. Read Drafts and confirmations for the full rules.
Revoke a key
Revoke a key in Settings > API keys or with Revoke an API key. Revoking is immediate: the next request with that key returns unauthenticated (401). Revoking is destructive, so through the API it needs "confirm": true.
Treat an API key like a password. Never put it in front-end code, a mobile app, a public repository or a support email. If a key leaks, revoke it straight away and create a new one.
Sessions (web app)
The web app signs you in with Better Auth and keeps the session in a secure, HttpOnly cookie. Unsafe requests carry a CSRF token. You do not use sessions from your own servers; they are listed here because they explain two behaviours you may see in the app:
- Active account. One login can be a member of several accounts. The session remembers which account you are working in. A session caller can also name the account with the
FIA-Account-Idheader (proposed). API keys and MCP tokens never need this header, because they are bound to one account. - Fresh sign-in. Sensitive actions ask you to sign in again, even if your session is still valid. The API returns
fresh_signin_required(401) when the session is too old.
Actions that need a fresh sign-in
- connecting a payment rail, deleting a business, changing billing,
- creating an
auto_sendAPI key, turning on auto-send for an automation, turning on "send automatically" for a store install, - connecting QuickBooks or Xero, adding your own AI key,
- buying a credit pack, adding a billing card, deleting the account.
API keys cannot perform these actions (proposed). Do them in the web app.
MCP tokens
AI assistants connect to the MCP server at https://mcp.freeinvoiceautomation.com/mcp. When you add the server, your assistant opens a sign-in page and a consent screen. There you choose the account, the scopes and the mode. The token you approve behaves like an API key: bound to one user and one account, limited to its scopes and to your current permissions, and draft_only unless you chose auto_send.
The MCP server also accepts an API key instead of OAuth, which is useful for clients that cannot do the OAuth flow. See MCP authentication.
Public tokens
Links that you send to clients, such as the pay page, the estimate page and the client portal, carry a public token instead of a key. Each token is 256-bit random, stored hashed, made for one purpose, expiring and revocable. Voiding an invoice revokes its pay token. These routes are listed under the Public pages and Client portal groups of this reference; your integration rarely calls them.
Errors you may see
| Code | Status | Meaning |
|---|---|---|
unauthenticated | 401 | No key, a wrong key, or a revoked or expired key |
fresh_signin_required | 401 | Sign in again in the web app, then retry |
permission_denied | 403 | The person behind the key lacks the permission |
scope_missing | 403 | The key itself was not given this scope |
business_out_of_scope | 403 | The key or member cannot reach that business |
member_deactivated | 403 | The member is deactivated in this account |
Every error includes a request_id. See Errors for how to fix each one.