Use a service account for CI and automation
Goal
You'll create a service account (dqsa_…), scope it to the workspace your pipeline works in, and use its token from CI, an orchestrator, the SDKs or the MCP server. A service account is the identity for automation: unlike a personal API key, it isn't tied to a person, so it keeps working when the person who set up the pipeline changes role or leaves.
Prereqs
- A super admin account. Creating a service account needs the manage-service-accounts permission, and a caller can only hand out authority it holds, so in practice a super admin creates them.
- You know which workspace the pipeline reads and writes.
Steps
-
Open Settings → Service Accounts and click Create service account.
-
Name it after what uses it (
dbt-ci,airflow-nightly), so the audit log and the list say who did what. -
Pick a role. The role decides what the service account may do, exactly as it does for a member. For a pipeline that registers assets, creates rules and runs validations, pick Editor. For a reporting job that only reads results, pick Viewer.
-
Pick the workspace. Editor, viewer and workspace admin service accounts are pinned to one workspace. See What a service account can reach.
-
Confirm your password if prompted. Creating a service account is step-up gated. If you sign in through SSO, the prompt offers Re-authenticate with provider instead.
-
Copy the token now. The raw
dqsa_…token is shown once. Measured Cloud stores only a hash. Put it straight into your CI secret store. If you lose it, revoke the service account and create a new one.
Use it
Send the token as a Bearer token. It works on the same endpoints a member uses, through either path:
- the workspace path,
/api/v{1,2}/organizations/{org_id}/workspaces/{workspace_id}/…; - the org path,
/api/v{1,2}/organizations/{org_id}/…, where the service account sees only its own workspace's rows.
Run a validation from CI:
curl -X POST \
-H "Authorization: Bearer $DQSA_TOKEN" \
"https://dq.example.com/api/v2/organizations/$ORG_ID/workspaces/$WS_ID/validations/$VALIDATION_ID/run"
The 202 response carries execution_run_id and parent_result_id, which you can poll. A run started by a service account is recorded with trigger api.
Ingest dbt artifacts after dbt build:
curl -X POST \
-H "Authorization: Bearer $DQSA_TOKEN" -H "Content-Type: application/json" \
"https://dq.example.com/api/v1/organizations/$ORG_ID/workspaces/$WS_ID/dbt/ingest" \
-d @payload.json
The SDKs and the Airflow and Dagster providers send their key as a Bearer token, so a dqsa_… token works wherever they take a dqk_… key. (With the dq-cloud-airflow-provider package, put the token in the connection's extra as api_key: that package treats a password that doesn't start with dqk_ as a login password.) The MCP server accepts only personal API keys.
What a service account can reach
A service account has its own role and scope. It reaches exactly the workspaces its scope grants, and inside them it can do what its role allows:
| Role | Scope | Reaches |
|---|---|---|
| Super admin | Org-wide (never pinned) | Every workspace in the organization. |
| Technical admin | Org-wide (never pinned) | Data sources in every workspace, and nothing else on the workspace surface. |
| Workspace admin | One workspace | That workspace only, with workspace-admin rights (including deletes that don't need step-up). |
| Editor | One workspace, or one team (API only) | That workspace only. Register data assets (including dbt ingest), create and edit rules and validations, run validations, and read results, alerts and incidents. |
| Viewer | One workspace, or one team (API only) | That workspace only, read-only. |
| Team admin | One team | Team membership management only. The role has no data permissions, so it can't read or run anything. |
Workspace scoping is enforced twice, on the route and on every row a request reads:
- A request for another workspace answers
403withService account is not scoped to this workspace. - A list through the org path returns only rows from the service account's workspace, and a row of another workspace answers
404. - A service account pinned to a team reaches that team's workspace and follows the same team rules as a team member: it sees workspace-shared rows and its own team's rows, but not rows restricted to another team.
The role still applies inside the scope. A viewer service account gets 403 Missing permission: … when it tries to create or run something.
An editor or viewer service account must be pinned. One with no workspace or team can't be created, and reaches nothing.
What a service account can't do
- Anything step-up gated. Step-up actions need an interactive user session with a recent password or SSO proof, and a long-lived token can never provide one. That covers creating or revoking credentials (including other service accounts), creating, editing or deleting a data source, deleting a validation, recycle-bin purges, SSO and membership changes, and org settings. The full list is in Step-up auth for sensitive actions. A service account gets
403with a message that says step-up needs an interactive session. It doesn't get the401 step_up_requiredchallenge, because re-authenticating can't help it. Do these actions in the app. - Org-level management while pinned. A workspace- or team-pinned service account can't manage org-level resources such as invites, domains or team rosters, whatever its role.
- Comment. Comments on results and incident timelines are attributed to a person, so they need a user session.
- Governance flips. Changing an asset's Restricted flag or its sample retention needs a person who is workspace admin, unless the service account is a super admin.
Revoke it
In Settings → Service Accounts, click Revoke on the row (or DELETE /api/v1/organizations/{org_id}/service-accounts/{id}). Revoking is step-up gated and takes effect at once: the cached lookup is cleared, and the next request with the token answers 401.
Verify
- The service account appears in Settings → Service Accounts with its role and its scope (Workspace-scoped, Team-scoped or Org-wide).
GET /api/v2/organizations/$ORG_ID/workspaces/$WS_ID/validationswith the token returns200. The same call for another workspace returns403(unless the service account is a super admin).- After you revoke it, the same call returns
401.