Documentation Get help

Authentication

Every REST request carries an API key as a bearer token. A key belongs to one organisation, holds an explicit list of permissions and expires after at most 90 days.

curl "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/teams" \
  -H "Authorization: Bearer $FLOWSTATE_API_KEY"

The Authorization header is the only place a key is read from.

The MCP server doesn’t use API keys; each person signs in with OAuth.

Key format

private_<identifier>_<secret>

identifier is 32 lowercase hexadecimal characters and secret is 64. The full key is shown once, when it’s created.

Create a key

You need the Create API Keys permission.

  1. Go to Settings → Users & Access → API Keys and select Create API Key.
  2. Name — the integration that will use it.
  3. Expiration — 7 days, 30 days (default), 60 days or 90 days.
  4. Permissions — tick what the integration calls; see Permissions by endpoint. You can only grant permissions your own role has; anything else fails with “Cannot grant permissions you do not have”.
  5. Select Create API Key and copy the key.

Admin-facing detail: Create and manage API keys.

Rotate and revoke

  • Rotate before the expiry date: create a key with the same permissions, deploy it, then revoke the old one.
  • Revoke from the key’s row (needs Revoke API Keys). The next request with that key returns 401.

Permissions by endpoint

A key’s permissions are fixed when it’s created. The checkbox label is in brackets.

EndpointsPermissions
/employees · /assignments/employees · /employees/{id}/salary-adjustmentsteam_employees_view · team_employees_create · team_employees_update · team_employees_delete (View / Create / Update / Delete Employees)
POST /vacancies/{id}/fillteam_employees_create (Create Employees)
/contractors · /assignments/contractors · /contractors/{id}/rate-adjustmentsteam_contractors_view · _create · _update · _delete (… Contractors)
/vacancies · /assignments/vacanciesteam_vacancies_view · _create · _update · _delete (… Vacancies)
/teams · /assignments/teamsteam_teams_view · _create · _update · _delete (… Teams)
/projectsroadmap_projects_view · _create · _update · _delete (… Projects)
/custom-attributessettings_entity_config_view (read) · settings_entity_config_update (create, update) · settings_entity_config_delete (… Entity Configuration)
/{resource}/{id}/custom-attributessettings_entity_config_view (read) · settings_entity_config_update (set, clear)
POST /business-metrics/readingsbusiness_metrics_ingest (Ingest Business Metric Readings)
/functional-groupsSee Functional groups.

Pay data also needs financials_view_detailed (View Detailed Financials):

  • GET /employees/{id}/salary-adjustments and GET /contractors/{id}/rate-adjustments
  • include=currentSalary or include=salaryHistory on employees
  • include=currentRate or include=rateHistory on contractors

Functional group requests are also limited to the areas and scenarios the key’s creator can currently access.

Errors

Authentication errors have code and message and no errorId.

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "API key has expired"
  }
}
StatusmessageCause
401Missing or invalid Authorization header. Expected: Bearer private_...No header, or it doesn’t start Bearer private_.
401Invalid API key formatNot private_ + 32 hex + _ + 64 hex.
401Invalid API keyNo such key.
401API key has been revoked
401API key has expired
403API key does not have access to this organizationorgId in the path isn’t the key’s organisation.
403API key lacks required permission: <permission>Add the permission by creating a new key.

403 bodies carry an errorId. All codes: Errors.

Handling keys

  • One key per integration, so one can be revoked alone.
  • Keep keys in a secrets manager or environment variable, never in source control or client-side code.
  • Alert on expiry: a key stops working on its expiry date with 401 API key has expired.