API Reference
API Keys

API Keys

API keys allow your systems and third-party tools to authenticate with the PurpletGo API without a user session. They are ideal for server-to-server integrations, HRIS webhook bridges, and automation pipelines.

For a general overview of authentication, see Authentication.


Key format

All PurpletGo API keys follow the same format: fnl_, an environment segment, then 32 hex characters.

PrefixEnvironment
fnl_live_Production
fnl_test_Sandbox / staging

Only the raw key's prefix (the first 12 characters, e.g. fnl_live_a1b) is stored for display - PurpletGo never stores or shows the full value again after creation.

An organisation can have at most 20 active keys at a time; creating a 21st fails until you revoke an unused one.


Scopes

Every API key is created with one or more scopes. Requests are rejected with 403 Forbidden if the key does not carry the required scope for the endpoint being called.

ScopeDescription
offboardings:readList and view offboarding records
offboardings:writeCreate offboardings and update their status
employees:readList employees
webhooks:readList registered webhooks
webhooks:writeCreate and delete webhooks
⚠️

Grant only the scopes your integration actually needs. A key with offboardings:write can trigger live offboarding workflows. Never embed production keys in client-side code or public repositories.


Endpoints

These management endpoints are for the PurpletGo dashboard itself - you authenticate with your regular session (cookie or Bearer JWT), not an API key, and they live under /api/keys rather than /api/v1.

List API keys

GET /api/keys

Returns all API keys for your organisation, most recently created first. Key values are never returned - only the stored prefix.

Required role: superadmin, admin, or hr.

Response 200 OK - a plain array, not wrapped in data/total:

[
  {
    "id": "3f9c8b1a-...",
    "name": "BambooHR Webhook Bridge",
    "key_prefix": "fnl_live_a3f",
    "scopes": ["offboardings:write", "employees:read"],
    "last_used_at": "2025-06-24T14:05:33Z",
    "expires_at": null,
    "revoked_at": null,
    "created_at": "2025-03-12T08:22:00Z",
    "created_by_name": "Jane Smith"
  }
]

Create an API key

POST /api/keys

Creates a new API key. The full key value is returned only in this response, in the raw_key field - store it immediately in a secrets manager.

Required role: superadmin, admin, or hr.

Request body

{
  "name": "Workday Offboarding Trigger",
  "scopes": ["offboardings:write", "employees:read"],
  "expires_at": "2026-12-31T00:00:00Z"
}
FieldRequiredTypeDescription
namestringLabel shown in the dashboard (max 80 characters)
scopes-string[]Defaults to all scopes if omitted
expires_at-date-timeMust be in the future; omit for a key that never expires

Response 201 Created

{
  "id": "6a1e2d90-...",
  "name": "Workday Offboarding Trigger",
  "key_prefix": "fnl_live_kx9",
  "scopes": ["offboardings:write", "employees:read"],
  "expires_at": "2026-12-31T00:00:00Z",
  "created_at": "2025-06-26T10:00:00Z",
  "raw_key": "fnl_live_kx9mrpwqlzdvntyja2cbs7hueog3"
}
⚠️

The raw_key field is returned exactly once. PurpletGo does not store the plaintext value. If you lose it, revoke the key and generate a new one.

An organisation is capped at 20 active keys - creating another returns 400 until you revoke one.


Revoke an API key

DELETE /api/keys/{keyId}

Immediately invalidates the API key. Any in-flight requests using this key will receive 401 Unauthorized. This action is irreversible.

Required role: superadmin, admin, or hr.

Response 200 OK

{ "message": "API key revoked" }

Returns 404 if the key doesn't exist in your organisation or was already revoked.


Using a key in requests

Pass the API key in the Authorization header as a Bearer token on every request:

curl https://app.purpletgo.com/api/v1/offboardings \
  -H "Authorization: Bearer fnl_live_kx9mrpwqlzdvntyja2cbs7hueog3" \
  -H "Content-Type: application/json"

Error responses

StatusMeaning
401Missing, malformed, revoked, or expired API key
403Key doesn't carry the scope required for the endpoint
429Key has exceeded 120 requests per 60 seconds

Every error follows the standard { "error": "..." } shape - see Errors & Rate Limiting.


Related