OnworkDevelopers

Authentication

Every request to the public API must carry a tenant API key. There are no sessions, cookies or OAuth flows: the key is the credential.

Key format

owk_<key_id>_<secret>
  • owk — fixed prefix (useful for secret scanners).
  • key_id — 16 hex characters, the public identifier of the key. It appears in the Onwork admin UI (owk_1a2b3c4d…) and is not secret.
  • secret — 64 hex characters. Onwork stores only a hash of it: the full key is visible only once, at creation time.

Sending the key

Primary header:

curl https://<host>/api/public/v1/users \
  -H "X-Api-Key: owk_your_key_id_your_secret"

Alternative — standard Authorization header:

curl https://<host>/api/public/v1/users \
  -H "Authorization: Bearer owk_your_key_id_your_secret"

Both are equivalent for authentication. The Bearer form additionally enables idempotent retries, which are scoped by the Authorization header.

Failure semantics

All credential failures return the same generic 401 — the API does not reveal whether a key exists, is revoked, expired or malformed:

{ "error": { "code": "unauthorized", "message": "Invalid or missing API key", "status": 401 } }

A 403 forbidden is different: your key is valid but is missing a scope, or a required platform module is not active for the company.

Key lifecycle

Event Effect
Created Active immediately; plaintext shown once.
Expired (expires_at) Requests return 401. Set expirations for temporary integrations.
Disabled Temporarily off (an admin can re-enable it).
Revoked Permanently off — a revoked key can never be re-enabled.

Rotation: create a new key with the same scopes, switch your integration, then revoke the old key. Keys are cheap; one integration = one key.

Storage best practices

  • Treat the key like a password: secret manager, never in source control.
  • Never log the full key. If you need to correlate, log the key_id part only.
  • If you suspect a leak, revoke immediately — revocation is instant.