Service accounts
Machine identities for CI pipelines and agents, managed from the console or the CLI.
Service accounts
A service account is a machine identity, separate from a human member, for
CI pipelines and agents that need to authenticate headlessly. It binds one of
the organization's roles (Owner, Admin, Editor or Viewer)
the same way a human member does, and authenticates with an OAuth2
client_id / client_secret pair rather than an interactive login.
Not a Zitadel personal access token
An older revision of docs/v2/modules/02-multi-tenancy/api.md describes
service accounts as issuing a Zitadel PAT. The console
(settings/service-accounts.tsx) and the backend it calls issue an OAuth2
client_credentials secret instead, consumed by
up0 auth login --client-id --client-secret. That doc page is stale; this
page reflects the code.
Creating the first one
The first service account for an organization is created from the console, Settings → Service accounts, gated to the Owner role. There is no headless bootstrap: something has to exist before anything can authenticate headlessly.
Managing accounts after that, from the CLI
Once you hold a valid session (interactive login, or an existing service
account), up0 service-accounts manages the rest.
Create
up0 --profile kind service-accounts create \
--name "1652 docs example" \
--username "docs-1652-example" \
--role editor✓ Service account "1652 docs example" created.
UP0_CLIENT_ID=docs-1652-example
UP0_CLIENT_SECRET=Sgabvr…redacted… (shown once, store it in your secrets manager)The secret is shown exactly once, here and nowhere else. There is no way to retrieve it again, only to rotate it for a new one.
List
up0 --profile kind service-accounts list Service Accounts
┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ id ┃ name ┃ role ┃ created_at ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ e98dcedb-a82a-4bfa-84… │ 1652 docs example │ editor │ 2026-09-16T13:27:33.0… │
└────────────────────────┴───────────────────┴────────┴────────────────────────┘--output json returns the full, untruncated id and every field.
Rotate
up0 --profile kind service-accounts rotate e98dcedb-a82a-4bfa-843a-34b133ab9175 --yes✓ Secret rotated. The prior secret no longer works.
UP0_CLIENT_ID=docs-1652-example
UP0_CLIENT_SECRET=Yqnwbv…redacted… (shown once, store it in your secrets manager)Rotating invalidates the previous secret immediately; anything still using it starts failing to authenticate.
Revoke
up0 --profile kind service-accounts revoke e98dcedb-a82a-4bfa-843a-34b133ab9175 --yes✓ Service account e98dcedb-a82a-4bfa-843a-34b133ab9175 revoked.A revoked account can no longer authenticate at all and stops appearing in
service-accounts list, though it is not deleted outright.
All four commands, and the console panel they mirror, are gated to the Owner role and server-enforced, not just hidden in the UI.
What a service account can call
Whatever its bound role permits, exactly like a human member with that role: an Editor-bound service account can create and edit resources but not manage billing or delete the organization; a Viewer-bound one is read-only. There is no separate, narrower permission model for machine identities; the same role catalog in Roles and permissions applies.
Ingestion tokens are a different thing
A service account authenticates a caller against the API (creating monitors,
reading issues, running CLI commands). It is not how telemetry gets in; that
uses a separate ingestion token created with up0 tokens create, unrelated
to any member or service account identity. See the ingestion guides under
Instrument your app for that flow.