Browse documentation
Landing Authentication

Authentication

Create workspace-scoped service accounts, exchange client credentials, and operate short-lived bearer tokens with least privilege.

View as Markdown

Authenticated Hodoflow APIs use an OAuth2-style service-account client_credentials exchange. There is no user-password API login, no long-lived bearer API key, and no refresh token.

An owner or admin creates the service account in the intended workspace, selects an active run-as member, and grants the smallest applicable scopes. The client ID and secret are then exchanged for a short-lived bearer token at POST /api/v1/oauth/token.

For the complete reproducible path, begin with Make your first API request.

Lifecycle at a glance

  1. Select the target workspace in the Hodoflow application.
  2. Create a specifically named service account.
  3. Choose an active run-as member whose access should bound the integration.
  4. Grant api_read, api_write, or webhooks only as required.
  5. Capture the client secret once into your normal secret manager.
  6. Exchange credentials and cache the token for slightly less than expires_in.
  7. Send Authorization: Bearer $TOKEN on protected requests.
  8. Rotate with an overlap window, then promote the staged pair.
  9. Revoke or deactivate immediately when access is no longer needed.

Token exchange

The canonical endpoint accepts JSON credentials or HTTP Basic authentication and requires grant_type: client_credentials. A successful response contains:

{
"access_token": "<redacted JWT>",
"token_type": "bearer",
"expires_in": 900
}

The lifetime is configurable; 900 seconds is the default. Trust the returned value instead of hard-coding it. Cache one token per service account, refresh slightly early, and coordinate concurrent refreshes so a fleet does not stampede the exchange endpoint. See Exchange credentials.

Runtime authorization

The bearer token identifies a service account, but it does not freeze mutable authorization until expiration. On every request Hodoflow reloads and validates:

  • the active service account and its current scopes;
  • the stored organization and workspace;
  • the selected run-as membership and its active state; and
  • the requested object's own authorization policies.

This makes deactivation, revocation, scope removal, workspace changes, and membership changes effective for already minted tokens. A 404 can mean an object is not visible to the run-as member; the API does not reveal filtered object existence.

Least-privilege scopes

Scope Purpose
api_read Safe JSON:API methods and GraphQL factQuery
api_write Unsafe JSON:API create/update operations
webhooks Webhook ingestion for triggers selecting this exact service account

Scopes do not replace the run-as member's authorization. The service account must pass both checks. Read Scopes and run-as permissions before granting write or webhook access.

Secret handling

Never put a client secret or bearer token in a URL, source file, committed .env, shell history, browser storage, analytics event, screenshot, generated share link, or support message. Use environment variables only as a handoff from your normal process secret store. Redact credentials and request bodies before logging; keep the non-secret x-request-id for correlation.

For safe rollover and emergency shutdown, continue with Rotate and revoke credentials.

Related documentation