Dashboard API
Read routes on the Trakr dashboard app. Export runs, workflow stats, alert history, and overview metrics from scripts, CI, or Grafana.
For SDK ingest (write path), see the Ingest API.
Base URL
https://app.trakr.run
Use your dashboard origin in local development (for example http://localhost:3000).
Authentication
Read access tokens (recommended)
Create a read access token in the dashboard under Settings → API Keys (Access tokens table). Admins create tokens; the full secret is shown once at creation.
export TRAKR_READ_TOKEN="tk_read_..."
Pass the token in the Authorization header on every request:
Authorization: Bearer tk_read_[32 hex chars]
- Tokens are org-scoped and read-only — separate from SDK ingest keys (
tk_live_…). - Valid only on the allowlisted GET routes below.
- Rate limit: 300 requests/minute per token; returns
429withRetry-After. tk_live_ingest keys are rejected on read routes;tk_read_tokens are rejected on ingest.- Never commit tokens to git or paste them into URLs — header only.
Session cookie (browser fallback)
The dashboard UI uses your Supabase session cookie. While logged in, browser DevTools sends cookies automatically. For one-off terminal tests, copy the cookie from DevTools → Application → Cookies.
Session cookies expire. Use read access tokens for CI, cron jobs, and long-lived integrations.
Write routes
POST, PATCH, and DELETE routes (billing, team, alert rules, token management) require a dashboard session. Bearer tokens are not accepted on write routes.
Allowlisted routes
Read access tokens work only on these GET handlers. All other routes return 401 for bearer tokens.
| Route | Notes |
|---|---|
| GET /api/runs | List runs |
| GET /api/runs/[runId] | Run detail |
| GET /api/runs/compare | Pro/Scale only — Starter returns 403 |
| GET /api/workflows | Workflow summaries |
| GET /api/workflows/[name]/stats | Workflow stats |
| GET /api/workflows/[name]/tools | Tool breakdown |
| GET /api/alert-events | Alert feed |
| GET /api/metrics/overview | Overview metrics |
GET /api/org/context is excluded in v1.
Rotation and revocation
- Create a new access token in Settings → API Keys with a descriptive name (e.g. "Grafana export v2").
- Update your integration to use the new token.
- Revoke the old token from the same page — sets
revoked_atimmediately; in-flight requests may complete but new requests return401. - Audit — the token list shows
last_used_atand prefix only; full secrets are never stored or returned after creation.
Rotate tokens when a team member leaves, after a suspected leak, or on a regular schedule for production integrations.
Security notes
- Store tokens in a secrets manager (CI variables, Vault, etc.) — not in repo files or chat.
- Logs and UI show the token prefix only (
tk_read_abcd…); never log the full secret. - Tokens grant read access to all org observability data on allowlisted routes — treat them with the same care as SDK ingest keys.
- Admin-only create/revoke; members can use a token an admin provides but cannot mint new ones.
Error format
{
error: string;
code?: string;
details?: unknown[];
}
| Status | Meaning |
|---|---|
| 401 | Missing, invalid, or revoked token; or missing session on session-only routes |
| 403 | Authenticated but not authorized (e.g. compare on Starter plan) |
| 404 | Resource not found or outside your organization |
| 429 | Rate limit exceeded — retry after Retry-After seconds |
GET /api/runs
List agent runs for your organization.
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
| workflow | string[] | all | Filter by workflow names (repeatable) |
| status | string[] | all | Filter by status |
| from | ISO datetime | 30 days ago | Inclusive start |
| to | ISO datetime | now | Inclusive end |
| cost_min | number | — | Minimum cost in USD |
| cost_max | number | — | Maximum cost in USD |
| sort | string | started_at_desc | started_at_desc, started_at_asc, cost_desc, cost_asc, duration_desc, duration_asc |
| cursor | string | — | Pagination cursor from a previous response |
| limit | number | 50 | Max 100 |
Response (200):
{
runs: AgentRunSummary[];
next_cursor: string | null;
total_count: number;
}
type AgentRunSummary = {
id: string;
workflow_name: string;
run_id_external: string | null;
status: "running" | "success" | "error" | "loop_detected" | "timeout";
cost_usd: string;
total_tokens: number;
duration_ms: number | null;
llm_call_count: number;
tool_use_count: number;
started_at: string;
ended_at: string | null;
};
GET /api/runs/[runId]
Full run detail with nested LLM calls, tool events, and direct child runs.
Response (200):
{
run: AgentRunDetail;
child_runs: AgentRunSummary[];
child_run_count: number;
combined_cost_usd: string;
alert_events: AlertEventSummary[];
}
alert_events includes up to five most recent alert firings for the run (newest first). Returns [] when none.
Response (404): Run missing or outside your organization.
GET /api/workflows
Aggregate stats per workflow.
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
| from | ISO datetime | 30 days ago | Inclusive start |
| to | ISO datetime | now | Inclusive end |
| sort | string | total_cost_desc | total_cost_desc, run_count_desc, error_rate_desc, avg_latency_desc |
Response (200):
{
workflows: WorkflowSummary[];
}
type WorkflowSummary = {
workflow_name: string;
run_count: number;
avg_cost_usd: string;
p95_cost_usd: string;
total_cost_usd: string;
error_rate: number; // 0.0–1.0
avg_duration_ms: number;
last_run_at: string;
};
GET /api/alert-events
List fired alert events for your organization. Export alert history for reporting, on-call digests, or internal dashboards.
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
| rule_id | string | all | Filter by alert rule ID |
| resolved | boolean | all | true = resolved only, false = unresolved only |
| from | ISO datetime | 30 days ago | Inclusive start |
| to | ISO datetime | now | Inclusive end |
| cursor | string | — | Pagination cursor from a previous response |
| limit | number | 50 | Max 100 |
Response (200):
{
alert_events: AlertEvent[];
next_cursor: string | null;
}
type AlertEvent = {
id: string;
alert_rule_id: string;
alert_rule_name: string;
run_id: string | null;
workflow_name: string | null;
triggered_value: number;
threshold_value: number;
notification_sent: boolean;
resolved_at: string | null;
created_at: string;
};
To mark an event resolved, use PATCH /api/alert-events/[eventId] from the dashboard UI or with a session cookie — read tokens cannot write.
GET /api/runs/compare
Side-by-side comparison of two runs in the same workflow. Pro and Scale plans only.
Query: run_a, run_b (UUIDs)
Response (403): Starter plan.
Example
export TRAKR_APP_URL="https://app.trakr.run"
export TRAKR_READ_TOKEN="tk_read_..."
curl -sS "$TRAKR_APP_URL/api/runs?limit=10&sort=started_at_desc" \
-H "Accept: application/json" \
-H "Authorization: Bearer $TRAKR_READ_TOKEN"
Grafana integration
Use the Infinity datasource plugin to pull Trakr workflow metrics into Grafana panels. Read access tokens are required — dashboard session cookies expire and are not suitable for Grafana.
1. Create a read token
In the Trakr dashboard: Settings → API Keys → Access tokens → create a token. Store the full tk_read_… secret in Grafana or your secrets manager.
2. Install Infinity
In Grafana: Connections → Add new connection → search Infinity → install the plugin.
3. Add a datasource
| Setting | Value |
|---|---|
| Type | JSON / URL |
| URL | https://app.trakr.run/api/workflows?from={ISO}&to={ISO} |
| Authentication | Bearer Token |
| Bearer token | Your tk_read_… token |
Use a 24h window for a "Workflow cost (24h)" panel, for example:
from: 24 hours ago (ISO 8601)to: now (ISO 8601)
4. Map fields (table panel)
| Infinity setting | Value |
|---|---|
| Root selector | workflows |
| Columns | workflow_name, total_cost_usd, run_count, error_rate |
Create a Table visualization. error_rate is 0.0–1.0 (multiply by 100 in Grafana field overrides if you prefer percentages).
5. Optional — recent runs panel
Second datasource or query:
- URL:
https://app.trakr.run/api/runs?limit=10&sort=started_at_desc - Root selector:
runs - Columns:
workflow_name,status,cost_usd,duration_ms,started_at
Troubleshooting
| Symptom | Fix |
|---|---|
| 401 Unauthorized | Token missing, wrong prefix, or revoked — create a new read token |
| Empty table | Check from/to cover a period with runs; widen the window |
| 403 on compare route | Expected on Starter — use /api/workflows or /api/runs instead |
Copy-paste snippets are also in the dashboard under Settings → API Keys → REST API quickstart → Grafana (Infinity plugin).
CI scheduled export
Schedule a daily pull of workflow cost and error stats from your own CI or cron infrastructure. Trakr does not run scheduled jobs — your pipeline calls GET /api/workflows with a read access token.
1. Create a read token
In the Trakr dashboard: Settings → API Keys → Access tokens → create a token. Store the full tk_read_… secret in your CI secrets manager.
2. Add GitHub Actions secrets
In your GitHub repo: Settings → Secrets and variables → Actions → add:
| Secret | Value |
|---|---|
| TRAKR_READ_TOKEN | Your tk_read_… token |
| TRAKR_APP_URL | https://app.trakr.run (or your dashboard origin) |
3. Add the workflow
Create .github/workflows/trakr-export.yml:
name: Trakr workflow export
on:
schedule:
- cron: '0 6 * * *' # daily 06:00 UTC
workflow_dispatch:
jobs:
export:
runs-on: ubuntu-latest
steps:
- name: Pull workflow stats (24h)
env:
TRAKR_APP_URL: ${{ secrets.TRAKR_APP_URL }}
TRAKR_READ_TOKEN: ${{ secrets.TRAKR_READ_TOKEN }}
run: |
TO="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
FROM="$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ")"
curl -sS -f "$TRAKR_APP_URL/api/workflows?from=${FROM}&to=${TO}" \
-H "Accept: application/json" \
-H "Authorization: Bearer $TRAKR_READ_TOKEN"
Run manually via Actions → Trakr workflow export → Run workflow to verify a 200 response with a workflows array.
4. Generic cron alternative
On a Linux host with curl and GNU date, add to crontab (crontab -e):
# Daily 06:00 UTC — set TRAKR_APP_URL and TRAKR_READ_TOKEN in ~/.profile
0 6 * * * TO=$(date -u +"%Y-%m-%dT%H:%M:%SZ"); FROM=$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ"); curl -sS "$TRAKR_APP_URL/api/workflows?from=$FROM&to=$TO" -H "Accept: application/json" -H "Authorization: Bearer $TRAKR_READ_TOKEN"
Security
- Rotate tokens via Settings → API Keys if a secret is leaked — revoke the old token after updating CI variables.
- Never commit tokens to git or embed them in workflow files.
Troubleshooting
| Symptom | Fix |
|---|---|
| 401 Unauthorized | Token missing, wrong prefix, or revoked — create a new read token and update secrets |
| Empty workflows array | Widen the from/to window or confirm runs exist in that period |
| curl: command not found | Install curl on the runner or host |
Copy-paste snippets are also in the dashboard under Settings → API Keys → REST API quickstart → CI / scheduled export.
Post to Slack
Optionally extend your CI job to post a daily summary to Slack after pulling Trakr workflow stats. Trakr does not receive or store Slack webhook URLs — your pipeline POSTs directly to Slack.
1. Create a Slack incoming webhook
In Slack: Apps → Incoming Webhooks (or create a Slack app with an incoming webhook) → choose a channel (for example #agent-costs) → copy the webhook URL.
2. Add the GitHub Actions secret
In your GitHub repo: Settings → Secrets and variables → Actions → add:
| Secret | Value |
|---|---|
| SLACK_WEBHOOK_URL | Your https://hooks.slack.com/services/... URL |
Keep existing TRAKR_READ_TOKEN and TRAKR_APP_URL secrets from the scheduled export setup.
3. Extend the export job
Add a second step (or combine into one shell script) after the Trakr API pull. GitHub-hosted ubuntu-latest runners include jq pre-installed.
# Requires: TRAKR_APP_URL, TRAKR_READ_TOKEN, SLACK_WEBHOOK_URL
TO="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
FROM="$(date -u -d '24 hours ago' +"%Y-%m-%dT%H:%M:%SZ")"
RESPONSE="$(curl -sS -f "$TRAKR_APP_URL/api/workflows?from=${FROM}&to=${TO}" \
-H "Accept: application/json" \
-H "Authorization: Bearer $TRAKR_READ_TOKEN")"
WORKFLOW_COUNT="$(echo "$RESPONSE" | jq '.workflows | length')"
TOTAL_COST="$(echo "$RESPONSE" | jq '[.workflows[].total_cost_usd | tonumber] | add // 0')"
SUMMARY="Trakr 24h: ${WORKFLOW_COUNT} workflows, \$${TOTAL_COST} total cost"
curl -sS -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"text\": \"${SUMMARY}\"}"
Example Slack message: Trakr 24h: 4 workflows, $12.34 total cost.
Security
- Trakr never receives or stores
SLACK_WEBHOOK_URL— only your CI runner uses it. - Rotate the Slack webhook and update the repo secret if the URL is leaked.
- Revoke and recreate read tokens separately if
TRAKR_READ_TOKENis exposed.
Troubleshooting
| Symptom | Fix |
|---|---|
| jq: command not found | Install jq on self-hosted runners; GitHub-hosted Ubuntu includes it |
| Slack invalid_payload | Ensure JSON is valid — escape quotes in the message body |
| Empty summary (0 workflows) | Widen the from/to window or confirm runs exist in that period |
Copy-paste snippet is also in the dashboard under Settings → API Keys → REST API quickstart → CI / scheduled export → Post summary to Slack.