Service tokens

Long-lived API keys for headless agents and CI pipelines.

JWTs are user-bound and browser-issued. That's fine for your dev box but awkward for a CI runner that has no browser. Service tokens are the answer: an art_* bearer string scoped to a single workspace and a single mode (rw / ro) with an explicit TTL.

Mint

artifacts key create \
    --workspace cases \
    --mode rw \
    --ttl 30d \
    --name panta-ci

The CLI prints the new key once:

Key created: art_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Save this. It will not be shown again.

Save it in your secret store (Fly secrets, GitHub Actions secrets, AWS SecretsManager, 1Password, etc.).

FlagMeaning
--workspace <name>Restrict the key to one workspace. Required for v0; unscoped keys are v1.
--mode rw | roCaps the maximum mount-session mode this key can request. An ro key cannot mount rw.
--ttl <duration>1h, 24h, 30d, etc. After expiry the key auto-revokes.
--name <label>Human label (shown in artifacts key list).

Use

Pass via the standard Authorization: Bearer … header. Or wire as the --token for artifacts login:

artifacts login --token "$PANTA_CI_KEY"

artifacts mount cases /mnt/work

The CLI doesn't care whether the bearer is a JWT or an art_* key; the orchestrator accepts both shapes.

What service tokens cannot do

Service tokens are user-class minus a few high-risk operations. They specifically cannot:

  • mint another service token (artifacts key create requires a user-class JWT);
  • create / delete workspaces (those are user-class operations too);
  • escalate from ro to rw mode at mount time (the per-key cap is enforced server-side).

This means a leaked CI key can't bootstrap into something more dangerous than what it already had access to.

List + revoke

artifacts key list
# ID                                   NAME       WORKSPACE   MODE   EXPIRES
# 8f3a2c91-...                         panta-ci   cases       rw     2026-06-02T...

artifacts key revoke <id>

Revoke is immediate. The next request bearing that key gets a 401 unauthorized: api key has been revoked.

Revoking a key does NOT terminate any mount sessions that the key had already issued. Mount sessions outlive their issuing token by design; the per-mount Redis ACL holds independently. To force-tear an in-flight mount, the customer has to artifacts unmount or you can delete the workspace.

Rotation

Mint a new key, deploy it to your CI / secret store, then revoke the old one. There's no built-in rolling-rotation; the same pattern as AWS access keys works fine.