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
- Send data into Hodoflow with a webhook — the full path, end to end.
- Embed a dashboard — embeds use a share token, not a service account.
- The developer portal covers the exchange and the token's claims in detail at authentication.