Skip to main content

Overview

Control-plane credentials for automation. Distinct from management keys (shipd_mgmt_) and SDK keys (shipd_sdk_). Related: Create a service account.

Format

The secret is returned only once on create. Store it securely; a lost token cannot be recovered. Send it as Authorization: Bearer shipd_sa_… or x-api-key.

Scopes

Scopes are { resource: [verbs] } matching the RBAC statement (e.g. { "flag": ["read", "create"] }). Empty scopes are rejected. A token cannot receive verbs the minting admin does not have. me always works so the CLI can resolve org (and project/environment when bound).

Binding

Environment-bound tokens only receive rows for their environment. They cannot create environments, perform project-wide flag definition changes, manage organization-wide approval policies, or request a project-wide snapshot rebuild. Resource IDs are resolved inside the token’s organization and are checked again against both the project and environment binding.

Lifecycle

Revocation preserves the token’s audit history. Repeated revoke requests succeed, so callers may safely retry them. rotateToken atomically creates a replacement with the same scopes and bindings and revokes the old token. The replacement plaintext is shown once; use a brief overlap only when the client can install the new credential before revoking the old one manually.

Rotation

Create a second token with the same minimal scopes and bindings, update the consumer’s secret store, verify one successful authenticated operation, then revoke the old token. Because plaintext is shown only once, a lost token cannot be recovered—rotate it. Disable the service account when every token must stop immediately.

Audit

Mutations made with a token record actorType: service_account and actorId = the service account id. tokenId identifies which token. Lifecycle events: serviceAccount.created, serviceAccount.updated, serviceAccount.disabled, serviceAccount.enabled, serviceAccount.deleted, serviceAccount.token.created, serviceAccount.token.revoked, serviceAccount.token.rotated. Successful mutating requests are audited with the token id. Successful authentication also records serviceAccount.token.used when lastUsedAt advances, at most once per minute. This makes the field a useful activity signal without turning the audit log into a request counter. Service-account tokens are control-plane-only. SDK routes accept only shipd_sdk_ credentials.