Authentication

JWT for user sessions, API keys for integrations

4 min read
Print this section

FreeMaint accepts two auth mechanisms: JWTs (issued by /auth/login, used by our web and mobile apps) and API keys (created in /company-settings/api, used by your own integrations).

JWT (user sessions)

  1. POST /auth/login — Body: {email, password}. Returns {access_token, refresh_token}.
  2. Send Authorization header — On every request: Authorization: Bearer <access_token>.
  3. Refresh when expired — POST /auth/refresh with the refresh_token to get a new access_token. Access tokens last 2 hours.

API key (server integrations)

  1. Open /company-settings/api or /profile/api-keys — Admins create keys in Company Settings > API, from the Business plan upward. A person whose role has the "Create personal API keys" permission creates their own under Profile > Security > API keys.
  2. Click 'New key' — Optionally set an expiration and an access level (Read only by default). The raw key is shown ONCE — copy it immediately.
  3. Use it — Send Authorization: Bearer fmk_<rawKey> on every request. Format: starts with fmk_ followed by 32 hex characters.

Security notes

  • API keys are stored as SHA-256 hashes — once you close the reveal dialog, the raw value is unrecoverable
  • Revoking a key disables it immediately; the row is kept for audit
  • Each key is scoped to a single company; cross-tenant requests always 401
  • Keys can have an optional expiresAt for short-lived integrations
  • Access levels, a ceiling on top of the owner's permissions: READ (the default — queries only), READ_STOCK (queries + adjustStock — ideal for a consume-only kiosk), FULL (every operation the owner's role allows)
  • Each key acts as its owner: every call carries their permissions and their data visibility, and what it writes is signed with their name. If the owner is deactivated, the key is refused (401, code API_KEY_OWNER_INACTIVE) until an admin hands it to another person in Company Settings > API — the key value does not change.

Testing an integration

There is no separate sandbox environment: an API key always addresses the real data of the company it belongs to. Two ways to test safely. (1) Sign up a second, free company and use it as your test tenant — the isolation between companies is the same mechanism that separates every customer, so nothing you do there can reach your production data. (2) For read-only work, create a key with the READ access level: it can run every query and no mutation, so it cannot change anything at all. When you are ready to write, a READ_STOCK key allows adjustStock and nothing else.

Tip

Compromise a key? Revoke it from /company-settings/api — takes effect within seconds.

Was this page helpful?