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:
- Settings → API tokens → New token.
- Pick a name, an expiry, and an optional description.
- 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_xxxxxxxxxxxxxxxxxxxxxxxxEvery 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
/eventsendpoint. 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_IDRevocation 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 saysBecause 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.