Recipes
Register and authenticate
One call gets you registered, signed in, and ready to explore — that part is easy. The choice that matters is what to use after. A User's token reaches every Account they manage; an Account's API key stays where it was minted. Once that distinction clicks, the development-vs-production decision becomes obvious. Here's the model and the calls.
account_id. An API key is minted for a
single Account and carries that scope implicitly.
Concepts
Two entities, two credentials. Each credential is the projection of one entity into a request — that's the part that makes the rest fall into place.
Entities
| Entity | What it is | Created by |
|---|---|---|
User | A person. Email + password. Can be a member of many Accounts. | POST /register |
Account | A workspace for one website. Holds visitor data, users, and API keys. | POST /register (default) or POST /accounts (extra) |
Roles
Every User holds a role per Account. The role gates what a token or API key minted under that User can do — not who you are, but what you may touch.
| Role | Code | Can do |
|---|---|---|
Administrator | 10 | Full access. Manages users, billing, subscriptions, invoices, and Account settings. |
User | 20 | Operational access. Reads visitor data and uses API keys, but cannot manage users, billing, or Account settings. |
Credentials
| Credential | Belongs to | Reach | Created by |
|---|---|---|---|
Token | User | Any Account the User has access to — pass account_id with each call. | POST /register, POST /login |
API key | Account | Only the Account it was minted for — account_id is implicit. | POST /api_key |
A token is who you are; an API key is where you can act. The token says
"I'm Jane, and I can manage these three accounts". The key says "this credential is good
for Acme's account, nothing else". Both are passed via
Authorization: Bearer <credential> — the API tells them apart by the
shape and by whether account_id is required.
Steps
Four moves get you from a brand-new account to a production-ready credential. Steps 1 and 2 issue tokens; step 3 mints the long-lived key; step 4 is the decision matrix.
1. Register
Creates a new User, a new default Account, and starts the free trial — all in one call.
Returns the User's token and the new default_account_id. No
prior credential needed.
/v1.3/register Prefer a form? The same flow lives at app.firmtrace.ai — sign-up there creates the User and Account, then you can pick up at step 3 to mint a key for automation.
| Parameter | Value | Why |
|---|---|---|
email | a real, deliverable address | Becomes the User. Free webmail and disposable domains are rejected. |
password | a strong password | Belongs to the User. Used for sign-in later. |
name | company name | Names the default Account. |
url | https://your-site.com | The website this Account will track. One Account per company. |
2. Sign in later
For an existing User. Returns a fresh token plus the User's
default_account_id. The token is the same shape as the one
/register hands out.
/v1.3/login | Parameter | Value | Why |
|---|---|---|
email | the User email | Identifies the User across all their Accounts. |
password | the User password | Authenticates the User. |
3. Mint an API key
Use the User's token plus an account_id to mint a key for that Account. The
full api_key value is returned only on creation — store it the moment you get
it. Subsequent reads expose only api_key_part.
/v1.3/api_key | Parameter | Value | Why |
|---|---|---|
account_id | the Account to mint for | Required when authenticating with a token. With an API key, scope is implicit. |
name | a reference label | Optional. Names the key so you know what it does later (e.g. "n8n-prod", "warehouse-sync"). |
end_date | YYYY-MM-DD | Optional. Disables the key on that date. A past date creates the key inactive — useful for pre-staging. |
4. Use the right credential
Tokens are great while a human is at the keyboard. API keys are what every automation, worker, or partner integration should hold.
| Use case | Credential | Why |
|---|---|---|
| Exploring the API in a notebook or curl | Token | Fastest path. You already have it from /login. |
| The product UI / dashboard | Token | A signed-in User needs cross-Account access. |
| A backend job, worker, or cron | API key | Scoped to one Account. Survives password rotations. Revocable per integration. |
| An n8n / Zapier / Make flow | API key | Same reasons. Name it after the flow so cleanup is obvious. |
| A partner or embedded SaaS integration | API key | One key per Account makes blast radius and billing clear. |
Anything that auto-runs should hold an account-scoped key. Three reasons: it can't reach accounts it wasn't minted for (blast radius stays scoped), it doesn't rotate when a User changes their password, and you can name it, end-date it, and revoke it without touching the User.
Considerations
- Password change rotates the token. Updating a User's password through
PATCH /userinvalidates the previous token; the response contains the new one. API keys are unaffected. - Full key value is returned only once. If you lose it before storing, mint a replacement and delete the old one — there is no "show again".
- Don't delete the key you're authenticating with. The DELETE invalidates it immediately and any in-flight calls fail. Mint the replacement first, switch over, then delete.
- One token, many accounts. A User with N accounts has N possible scopes
for the same token. Always pass
account_idon token-authenticated calls; an API key carries it implicitly. - Pre-stage keys for rollouts. POST
/api_keywith anend_datein the past creates an inactive key. PATCH theend_dateforward when you're ready to flip it on — useful for handing credentials to a partner before they go live. - One trial per company. Accidental duplicates are tolerated; intentional re-registration of the same domain leads to permanent blocking.
Errors & retry
Sort responses into four buckets and handle each on its own terms.
| Bucket | Examples | What to do |
|---|---|---|
| Wrong credentials | 401 login_error | Stop. Wrong password — retrying does not help. |
| Trial rejected | 403 email_format_register | Stop. Free webmail or unsupported address — surface the user_message. |
| Transient | network, 5xx, 429 | Retry with exponential backoff. Respect Retry-After on 429. |
| Success | 200 | Persist the credential — token + account_id, or the full api_key (only returned once). |
From /register and /login, persist token and
default_account_id together — they're useless apart. From
/api_key, persist the full api_key immediately and the
api_key_part alongside as the handle for later PATCH/DELETE.
See also Poll for new and updated companies