Browse documentation
Guide Updated 11 August 2026

Service accounts

Create a client ID and secret for a machine, scope what it can do, and decide whose permissions it runs with.

View as Markdown

A service account is how something that is not a person authenticates with your organization. A webhook sender, a script that reads records, a page embedding a dashboard — each gets its own credential, its own scopes, and its own audit trail.

Outcome

An external caller can authenticate as your organization with a credential you can revoke on its own, without sharing anyone's login.

Before you start

Service accounts live at Settings → Service Accounts. Creating and editing one, and viewing its credentials, is limited to organization owners and admins.

1. Create one

New Service Account asks for three things.

Name is for you. Name it after the integration that will hold it — Stripe webhook ingest — so revoking the right one later is obvious.

Scopes decide what the credential is allowed to do. At least one is required.

Scope Grants
webhooks Sending data into Hodoflow through webhook requests.
api_read Read-only REST access to workflows, runs, and warehouse records.
api_write Any JSON API request that is not a read.
embed Loading dashboards inside external sites through the embed channel.

Grant the narrowest set that works. A webhook sender needs webhooks and nothing else.

Run as is the one that surprises people. A service account does not have permissions of its own — it borrows a member's. Pick an organization member and every request authenticated with this credential executes as them, respecting their permissions. Only active members of the current organization are offered.

That means deactivating a person can change what a service account can reach. Point machine credentials at whoever should own the integration long-term.

Checkpoint: the account is listed as Active with the scopes you chose.

2. Copy the client ID and secret

Creating the account mints a pair: a client ID beginning cid_ and a client secret beginning csec_. Neither embeds anything about your organization, so neither is safe to treat as public.

Client Credentials on the service account's page shows both, each with a Copy button. Unlike most secrets, these stay retrievable — come back to this page whenever an integration needs reconfiguring. Access is limited to owners and admins.

Checkpoint: both values are stored somewhere you control.

3. Exchange them for an access token

The pair is not what you send with a request. Exchange it for a short-lived token first:

curl -X POST https://app.example.com/api/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "cid_...",
"client_secret": "csec_..."
}'

You can also send the pair as HTTP Basic auth instead of in the body. The response is the token, its type, and its lifetime in seconds:

{"access_token": "eyJ...", "token_type": "bearer", "expires_in": 900}

Fifteen minutes, so a long-lived integration exchanges again rather than caching the token forever. Send it as Authorization: Bearer <access_token>.

A token carries the scopes and the run-as member that were set when it was issued, which is why a scope change takes effect on the next exchange rather than instantly.

Checkpoint: an authenticated request succeeds. For a complete worked example, see Send data into Hodoflow with a webhook.

Rotating, deactivating, and deleting

Staging and promoting a new secret, checking what depends on a credential, and removing one safely are all on Naming, reuse, rotation, and deletion.

Common problems

Every credential error looks the same. Missing credentials, a wrong secret, an unknown client, and a deactivated account all return 401 with {"error": "invalid_client"}. That is deliberate. Check the account's status in Hodoflow rather than reading the error.

403 on a request that used to work. The token predates a scope change. Exchange again.

The account is not offered in the webhook trigger wizard. Only active service accounts holding the webhooks scope are listed. Check both, then reopen the wizard.

Deactivating is refused. An active workflow's trigger authenticates with it. Usage on the service account's page lists which; deactivate those workflows first.

I cannot see Client Credentials. That page is limited to owners and admins.

Next step

Related documentation