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

> ## Agent Instructions
> Use Stable documentation by default. Honor an explicit Beta request or a URL under /docs/beta/. If the requested version conflicts with the installed CLI package or API origin, clarify the target before writing integration code.
> Pages under /docs/beta/ document Beta; other product pages document Stable. Keep the CLI package, commands, API origin, and credentials within the selected version. State the documentation version in your answer.
> For MCP search, always pass version: Stable or version: Beta. Unfiltered search mixes both versions. For filesystem reads, keep Beta queries under /beta/ and exclude /beta/ from Stable queries; discover paths before reading them.
> The public docs base is https://photon.codes/docs. Convert MCP page paths to public URLs under that base, preserving /beta/ when present. Read https://photon.codes/docs/skill.md for version selection and https://photon.codes/docs/llms.txt for the version indexes.

# Service keys

> Give CI and other automation a non-interactive Photon credential.

An **Account Service Key** is a long-lived machine credential for your account.
Use one wherever a browser-based [device login](/docs/beta/cli/authentication) is not
possible — CI jobs, cron tasks, deployment scripts.

A service key acts as your account. Treat it like a password.

[Browse the automatic command reference](/docs/beta/cli/reference/index).

## Create a key

Every key needs a name and an explicit expiry decision. Pass either
`--expires-at` with an RFC 3339 timestamp, or `--no-expiry`:

```sh theme={null}
photon account service-key create \
  --name "Deploy pipeline" \
  --expires-at 2027-01-01T00:00:00Z
```

```sh theme={null}
photon account service-key create --name "Deploy pipeline" --no-expiry
```

Names are limited to 128 characters. An expiry must be in the future and no
more than 3650 days out.

<Warning>
  The credential is printed **once**, when the key is created. `list` and
  `revoke` never return it. Copy it into your secret store before the command
  scrolls away.
</Warning>

## Sign in with a key

`photon login --service-key` reads one complete credential from
**non-interactive stdin**. The CLI refuses to read it from a terminal, so it
never lands in your shell history or in the process list:

```sh theme={null}
printf '%s' "$PHOTON_SERVICE_KEY" | photon login --service-key
```

In GitHub Actions:

```yaml theme={null}
- name: Sign in to Photon
  run: printf '%s' "$PHOTON_SERVICE_KEY" | photon login --service-key
  env:
    PHOTON_SERVICE_KEY: $
```

The CLI verifies the key against Photon before storing it. If you are already
signed in, add `--force` to replace the current session:

```sh theme={null}
printf '%s' "$PHOTON_SERVICE_KEY" | photon login --service-key --force
```

Add `--insecure-storage` on machines with no OS keychain — most CI runners.
See [where credentials are stored](/docs/beta/cli/authentication#where-credentials-are-stored).

After signing in, every other command works exactly as it does for a human
session:

```sh theme={null}
photon whoami --json
photon project list --json
```

## List and revoke keys

`list` shows unrevoked keys only, never the credentials themselves:

```sh theme={null}
photon account service-key list
photon account service-key list --json
```

Revocation is immediate and cannot be undone:

```sh theme={null}
photon account service-key revoke pho_ask_01jd... --force
```

`revoke` asks for confirmation unless you pass `--force`. Automation must pass
it, since a non-interactive command with no answer exits with code `2`.

## Credential format

A service key is a `pho_ask_` prefix, a 26-character key ID, and a secret. The
key ID is the part you pass to `revoke` and the part that appears in `list`
output. The whole credential is at most 512 bytes and must be piped in exactly
as issued, with no surrounding whitespace beyond a single trailing newline.

## Recovery

`create` and `revoke` are journaled mutations. If the network fails after the
request leaves your machine, the result is recorded and you can replay it —
see [Recoverable operations](/docs/beta/cli/operations). This matters most for `create`,
where a lost response means a lost credential.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.