Skip to content
FirmWorks

API

Build on FirmWorks

The public API rolls out one module at a time. Per-org API keys are live; route consumption is in flight. This page lists what’s available today and what’s queued.

Get a key

Sign in to your workspace and open /app/settings/api-keys. Click Create key, give it a name and a scope (read, write, or admin), and copy the full secret immediately — we hash before storing, so we can’t show it again.

Keys can be revoked from the same page at any time. Revoked keys stop authenticating requests within seconds. Each key shows its last-used timestamp so you can spot stale ones.

Key format

fw_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789

Authentication

Pass your key as a Bearer token on every request. The API derives your organization from the key — the key is scoped to one workspace, so there’s no per-request org parameter.

curl -H "Authorization: Bearer fw_<your_key>" \
     https://firmworks.com/api/v1/contacts

All API responses are JSON. Errors come back as { "error": { "code": "...", "message": "..." } } with a meaningful HTTP status (400 / 401 / 403 / 404 / 429 / 500).

For the full scope semantics — read vs write vs admin, what the wrapper checks before the handler runs, why hashes are rotated on revoke — see the security overview.

Quickstart

Sixty seconds, three commands — create a key, hit /api/v1/me, confirm you’re wired up.

  1. 1. Create a key in the UI

    Sign in, open /app/settings/api-keys, click Create key, pick scope read, copy the full fw_… secret. You only see it once.

  2. 2. Export the key locally

    export FW_KEY="fw_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789"
  3. 3. Hit /api/v1/me to confirm auth

    curl -s -H "Authorization: Bearer $FW_KEY" \
         https://firmworks.com/api/v1/me | jq .

    Expected response:

    {
      "data": {
        "apiKeyId": "akey_…",
        "orgId": "org_…",
        "orgName": "Your Workspace",
        "orgSlug": "your-workspace",
        "scopes": ["read"]
      }
    }

    Got a non-200? Status 401 means the key is invalid or revoked; 429means you’ve tripped the per-key rate limit (see below).

Available surface

Live items work today. Coming soonitems are committed for the current quarter — see the roadmap for status.

API keys

Live
  • Manage workspace keys at /app/settings/api-keys
  • Plaintext shown once on creation; only the SHA-256 hash is stored
  • Per-key scope (read · write · admin) and last-used timestamp

Identity

Live
  • GET /api/v1/me — returns { apiKeyId, orgId, orgName, orgSlug, scopes }
  • Authenticated by withApiKeyAuth — verifies hash, checks revoked_at, updates last_used_at
  • Doubles as a smoke test before hitting the real CRUD endpoints

Documents & Tax

Coming soon
  • GET /api/v1/contacts — list, filter, paginate
  • POST /api/v1/contacts — create with tax ID
  • GET /api/v1/documents — invoices, quotations, receipts
  • POST /api/v1/documents — issue a new document with VAT/WHT

Outbound webhooks

Coming soon
  • Subscribe to invoice.created / project.completed / member.added
  • HMAC-SHA256 signed POSTs (X-FirmWorks-Signature header)
  • Retry with exponential backoff; manual retry from the UI

Rate limits

Default cap is 100 requests per minute per key across all endpoints. Burst slack: brief spikes above the cap are tolerated; sustained load triggers HTTP 429 with a Retry-After header. Need a higher limit for an integration? Email hello@firmworks.com.

Need help?

Email hello@firmworks.com with what you’re trying to build — we answer within one business day, Bangkok hours, and we’ll tell you honestly whether the endpoint you need is on the path.