PlatformPersonal access tokens

43. Personal access tokens

The durable credential for scripts, CI, and the automation API — anything you can do in the UI, you can do over HTTP.

Daalu has a full HTTP API. Anything you can do in the operator app you can do over the API, with the same permissions. The credential for scripting use is a personal access token (PAT).

This chapter covers minting, using, and rotating PATs. For the full endpoint map, see Chapter 53 — API reference.


Minting a PAT

The UI lives in Settings. In short:

  1. Settings → API tokens → New token.
  2. Pick a name, an expiry, and an optional description.
  3. Copy the token now. It’s shown exactly once.

The token looks like dpat_xxxxxxxxxxxxxxxxxxxxxxxx. The dpat_ prefix is intentional — it’s recognizable in env files and greppable for the day you wonder “is this a Daalu token?” Daalu stores only a hash of the value plus the first few characters (so the UI can show you which token a row is without ever holding the secret).

You can also mint a PAT over the API itself:

curl -X POST https://ops.daalu.io/api/v1/auth/tokens \
  -H "Authorization: Bearer $EXISTING_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name": "ci-deploy-bot", "expires_in_days": 90}'

The response carries the cleartext token once — capture it from that response and store it immediately.


Using a PAT

Send it as a bearer token in the Authorization header:

GET /api/v1/alerts HTTP/1.1
Host: ops.daalu.io
Authorization: Bearer dpat_xxxxxxxxxxxxxxxxxxxxxxxx

Every authenticated endpoint accepts both a PAT and the browser’s session cookie — the PAT path looks the token up by hash directly. The tenant is resolved from the token, so you never pass a tenant ID.

A curl walkthrough you can adapt:

TOKEN="dpat_xxxxxxxxxxxxxxxxxxxxxxxx"
BASE="https://ops.daalu.io/api/v1"
 
# List firing alerts
curl -H "Authorization: Bearer $TOKEN" \
  "$BASE/alerts?severity=critical"
 
# Acknowledge one
curl -X POST -H "Authorization: Bearer $TOKEN" \
  "$BASE/alerts/$ALERT_ID/acknowledge"
 
# Run a structured query over the timeline
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entity": "alerts", "since_hours": 168}' \
  "$BASE/reports/query"
 
# Pull this month's spend
curl -H "Authorization: Bearer $TOKEN" "$BASE/billing/current"

Note: Emitting events into Daalu (CI deploy markers, custom heartbeats) does not use a PAT — it uses your tenant’s ingest key on the /events endpoint. See Chapter 40 — Webhooks. PATs are for everything else: reading, querying, and acting through proposals.


What a PAT can do

Exactly what the user it was minted for can do. A regular user’s PAT can investigate but can’t mutate integrations; an admin’s PAT can do everything an admin can.

PATs do not bypass the four-eyes approval rule. A PAT-driven proposal can’t be self-approved by another PAT belonging to the same user — approval still needs a second human.


Expiry and rotation

When you mint, you pick an expiry: never, 30 / 90 / 365 days, or custom. Best practice:

  • 365 days for human-managed scripts. Put a rotation on your calendar.
  • 30–90 days for CI pipelines. Automate rotation through your secret store.
  • Never is allowed but discouraged. Tokens you never rotate are tokens that eventually leak.

To rotate, mint a new token, deploy it everywhere the old one was used, then revoke the old one. To revoke immediately, delete it:

curl -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://ops.daalu.io/api/v1/auth/tokens/$TOKEN_ID

Revocation takes effect on the token’s next request, which gets a 401.


A worked automation

A nightly sweep that flags critical alerts still firing after 24 hours:

import os, requests
 
BASE = "https://ops.daalu.io/api/v1"
TOKEN = os.environ["DAALU_TOKEN"]
headers = {"Authorization": f"Bearer {TOKEN}"}
 
alerts = requests.get(
    f"{BASE}/alerts",
    params={"severity": "critical"},
    headers=headers,
    timeout=30,
).json()
 
for a in alerts:
    print(a["id"], a["summary"])
    # ...page Slack, open a ticket, whatever your runbook says

Because the PAT carries the same permissions as you, this script sees exactly the alerts you’d see in the UI — no more, no less.


Best practices

  • Store tokens in a secret store. Not in code, not in config committed to git. Vault, AWS Secrets Manager, GCP Secret Manager, Doppler — any of them.
  • One token per use case. Don’t share a single token across CI, ops scripts, and a personal one-off. Rotation blast radius stays per-use-case.
  • Watch the last-used column. A token unused for 60 days is a token you can probably revoke.
  • Use admin-minted PATs for shared automation accounts. An admin can mint on behalf of a service-style user — see Chapter 6 — Invite your team.

PAT vs JWT

The browser session uses short-lived JWTs (about an hour, refreshed silently). For scripting, PATs are strictly better:

  • They don’t expire mid-job.
  • They rotate independently of a login.
  • They’re recognizable by prefix and revocable individually.

For anything non-interactive, use a PAT.


Next: Chapter 44 — The Daalu-hosted AI tier