> ## Documentation Index
> Fetch the complete documentation index at: https://datum.net/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Service accounts

> Authenticate datumctl non-interactively with a service account credentials file for CI, automation, and headless environments.

Service accounts let `datumctl` authenticate without a human at the keyboard. Instead of opening a browser, you point the CLI at a credentials file, and it signs in as the service account's machine identity. Use this for continuous integration jobs, scheduled automation, and any headless runner where an interactive login is not possible.

<Info>
  Service accounts are **created in the Datum Cloud portal**, which is where you generate and download the credentials file. This page covers **using** those credentials with `datumctl`. To create a service account and download its key, see the portal guide on [service accounts](/platform/service-accounts).
</Info>

## When to use a service account

Choose the authentication method that matches who — or what — is running the command:

<CardGroup cols={2}>
  <Card title="Interactive login" icon="user">
    A person at a terminal. Run `datumctl login` to authenticate through your browser (or `datumctl login --no-browser` for a device-code flow). Credentials refresh automatically and are tied to your user identity.
  </Card>

  <Card title="Service account" icon="robot">
    A pipeline, cron job, or agent with no human present. Run `datumctl login --credentials <file>` to sign in as a machine identity using a downloaded credentials file.
  </Card>
</CardGroup>

Service accounts are the right choice when:

* The command runs unattended, so no one can complete a browser or device prompt.
* You want a dedicated, auditable identity for automation rather than a personal account.
* You need the same credentials to work reproducibly across many runners.

## Log in with a credentials file

Once you have downloaded a credentials JSON file from the portal, authenticate by passing its path to `datumctl login`:

```bash theme={null}
datumctl login --credentials ./my-service-account.json
```

`datumctl` reads the file, requests an access token for the service account, and stores the resulting session so subsequent commands are authenticated. After login you can run any command as the service account:

```bash theme={null}
datumctl get organizations
```

<Note>
  Service-account login is non-interactive: it does **not** open a browser and does **not** prompt you to pick a context. Set the organization or project your commands should target explicitly — see [Contexts & scoping](/datumctl/contexts-and-scoping) — or pass `--organization` / `--project` on each command.
</Note>

### Targeting a custom environment

The credentials file is issued for a specific Datum Cloud environment. For a self-hosted or otherwise custom environment, also pass that environment's auth hostname so token discovery points at the right server:

```bash theme={null}
datumctl login --credentials ./my-service-account.json --hostname auth.example.com
```

The default `--hostname` is `auth.datum.net` (production). You normally do not need `--api-hostname` — `datumctl` derives the API server from the auth hostname — but you can override it if your environment requires a specific API endpoint.

### Confirming the active identity

To verify which identity is active, use:

```bash theme={null}
datumctl whoami
```

The service account also appears in the local account list, where its `client_email` is shown as the name:

```bash theme={null}
datumctl auth list
```

## The credentials file

The credentials file is a JSON document you download from the portal. It looks like this:

```json theme={null}
{
  "type": "datum_service_account",
  "client_email": "ci-deployer@example",
  "client_id": "1234567890",
  "private_key_id": "abc123",
  "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n",
  "token_uri": "https://auth.datum.net/oauth/v2/token",
  "api_endpoint": "https://api.datum.net",
  "scope": "openid profile email offline_access"
}
```

Key fields:

| Field                                | Purpose                                                                     |
| ------------------------------------ | --------------------------------------------------------------------------- |
| `type`                               | Must be `datum_service_account`. `datumctl` rejects any other value.        |
| `client_id`                          | The service account's identity. **Required.**                               |
| `private_key_id`                     | Identifies which signing key is in use. **Required.**                       |
| `private_key`                        | PEM-encoded private key used to sign the login request. **Required.**       |
| `client_email`                       | Human-readable identity, shown as the account name in `datumctl auth list`. |
| `token_uri`, `api_endpoint`, `scope` | Environment and authorization details carried in the file.                  |

<Warning>
  The credentials file contains a **private key**. Treat it like a password: never commit it to source control, restrict its file permissions, and store it in your CI system's secret manager. Anyone with the file can authenticate as the service account.
</Warning>

If login fails, `datumctl` reports exactly what is wrong — a missing required field, an unreadable file, or a `type` that is not `datum_service_account` — so you can correct the file and retry. To inspect the token request in detail while troubleshooting, add `--debug`, which prints the login JWT's claims to standard error.

## Credential storage on headless runners

After a successful login, `datumctl` stores the session in your operating system's keyring. On many headless CI runners no system keyring is available, so `datumctl` automatically falls back to an on-disk file at `~/.datumctl/credentials.json`.

This fallback is expected on CI, but note:

* The file is written with owner-only (`0600`) permissions, but is **not encrypted**. Treat the runner's home directory as sensitive and use ephemeral runners where possible.
* When the fallback engages, `datumctl` prints a one-time warning noting that it is using file-based credential storage. This is informational — your commands still work.

<Note>
  Because the fallback file is unencrypted, prefer runners whose home directory is discarded after the job completes, and rely on your CI secret manager as the source of truth for the credentials file rather than persisting the stored session.
</Note>

## Related

* [Create a service account in the portal](/platform/service-accounts) — generate the credentials file this page consumes.
* [Automating datumctl in CI/CD](/datumctl/cicd/automating) — wire service-account login into any pipeline, with credential helpers and structured errors.
* [GitHub Actions](/datumctl/cicd/github-actions) — install and authenticate a service account in a GitHub workflow in one step.
* [Logging in](/datumctl/auth/logging-in) — the interactive browser and device-code flows for humans at a terminal.
* [Managing accounts & tokens](/datumctl/auth/managing-accounts) — list sessions, switch the active identity, and print access tokens.
* [Contexts & scoping](/datumctl/contexts-and-scoping) — set the organization or project your automated commands target.
* [Output formats & scripting](/datumctl/output-and-scripting) — machine-readable output and structured errors for automation.
