Open the console

API

Usage and analytics

What your runs cost and how they behaved: the platform's charges summed or row by row, what each agent consumed, one run's charge, and the time series the console's charts are drawn from.

None of these checks a credential's project scope

Every route here answers for the whole tenant. project narrows the answer when you pass it; it is not checked against the project a service user was issued for, so a scoped credential reads every project's costs, usage and run history.

A window is half-open, and naive times are UTC

since is inclusive and until exclusive, so adjacent windows never count one charge twice. On the /v1/analytics series a timestamp with no zone is read as UTC; send one with a zone everywhere else.

The samples use $API and $TOKEN, which the API overview sets. Your own balance and your users' wallets are on the wallets page; what a run did is GET /v1/runs/{invocation_id} on the invocations page.

Which route answers which question

You wantCallFrom
what the platform charged you over a periodGET /v1/cost/summarythe ledger
how one of those charges was pricedGET /v1/costthe ledger
what each agent has consumed, all timeGET /v1/usagethe ledger
which run a charge came fromGET /v1/usage/holdsthe ledger
what one run cost, by model and toolGET /v1/usage/invocations/{id}the ledger, plus the run record
what your users paid you, over timeGET /v1/analytics/revenuethe ledger
platform charges and settled tokens, over timeGET /v1/analytics/cost, /tokensthe ledger
runs, failures, latency and tool calls, over timeGET /v1/analytics/invocations, /latency, /toolsthe analytics warehouse
recent runs, and one run's traceGET /v1/analytics/runs, /runs/{id}/tracethe analytics warehouse, plus the run record

Money is micro-USD; your tenant's own holds are tokens

Every micros and charge_micros here is a whole number of micro-USD: 1,000,000 is one dollar. A hold's reserved_units and settled_units are in the unit of the account that paid — tokens for your tenant, micro-USD for a user's wallet — so never chart them as either without reading account_id first.

What the platform charged you, summed

GET/v1/cost/summarydeploy-service

Your platform charges over one window, summed per project, workload, agent and SKU — and per time bucket as well when you pass a grain, so a chart and the table under it come from one read.

A window is required

A sum means nothing without the period it covers, so since and until are both required here; leave either out and the route answers 422 before it asks the ledger anything. Summing the bucketed rows gives the unbucketed answer exactly.

unpriced says a figure is incomplete, not free

A row no rate card has priced yet carries a charge of zero, and unpriced counts how many such rows went into the sum. Unpriced usage is charged once it is priced, not dropped.

The ledger's own refusals come back as 502

This route passes since, until and grain to the ledger unchecked. An unknown grain or a timestamp the ledger cannot parse is refused there, and reaches you as a 502 whose message carries the ledger's sentence.

Request
curl "$API/v1/cost/summary?since=2026-10-01T00:00:00Z\
&until=2026-11-01T00:00:00Z&grain=day&project=salmon" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
sincequeryrequiredISO timestamp, inclusive.
untilqueryrequiredISO timestamp, exclusive.
grainqueryoptionalhour, day, week or month. Omitted, one row per group for the whole window and no bucket.
projectqueryoptionalOne project. Omitted, every project in the tenant.

Responses

StatusMeaning
200{rows, since, until, grain}.
401No token, or one that did not verify.
422since or until missing, or a project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger refused or could not answer — including an unknown grain or an unparseable timestamp.

Response body

{
  "since": "2026-10-01T00:00:00Z",
  "until": "2026-11-01T00:00:00Z",
  "grain": "day",
  "rows": [
    {
      "bucket": "2026-10-14T00:00:00+00:00",
      "project_slug": "salmon",
      "workload": "hotel-concierge",
      "agent": "hotel-concierge",
      "sku": "compute.cpu",
      "sku_name": "CPU reserved",
      "unit": "core-second",
      "quantity": 21600.0,
      "charge_micros": 108000,
      "unpriced": 0,
      "periods": 24,
      "first": "2026-10-14T00:00:00+00:00",
      "last": "2026-10-14T23:00:00+00:00"
    }
  ]
}

The charges, row by row

GET/v1/costdeploy-service

The raw accruals behind those sums: one row per workload, SKU and metering period, newest first, each with the rate it was priced at.

Do not add up a page of these and call it a total

A month of hourly rows is thousands, and the default page is 200. Ask /v1/cost/summary for a total; read these to check how one figure was arrived at.

priced and charged answer different questions

priced is whether a rate card has set a price for the row; charged is whether money moved, which a row priced at zero never does. On a tiered price, quantity × rate_micros does not reproduce charge_micros — tier_prior_quantity is where in the month the row was priced from.

Request
curl "$API/v1/cost?project=salmon&since=2026-10-14T00:00:00Z&limit=100" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
sincequeryoptionalISO timestamp. Omitted, no lower bound. One the ledger cannot parse is a 502.
untilqueryoptionalISO timestamp. Omitted, no upper bound.
projectqueryoptionalOne project. Omitted, every project in the tenant.
limitqueryoptionalDefault 200, clamped to 1–1000.
offsetqueryoptionalDefault 0.

Responses

StatusMeaning
200{cost, total}.
401No token, or one that did not verify.
422A project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger refused or could not answer, including an unparseable date.

Response body

{
  "total": 742,
  "cost": [
    {
      "tenant_id": "acme",
      "project_slug": "salmon",
      "workload": "hotel-concierge",
      "agent": "hotel-concierge",
      "sku": "compute.memory",
      "sku_name": "Memory reserved",
      "quantity": 1800.0,
      "unit": "gib-second",
      "period_start": "2026-10-14T13:00:00+00:00",
      "period_seconds": 3600,
      "rate_card": "rc-2026-10",
      "rate_micros": 1,
      "charge_micros": 1800,
      "tier_prior_quantity": 0,
      "priced": true,
      "charged": true
    }
  ]
}

What each agent has consumed

GET/v1/usagedeploy-service

Lifetime totals per project, agent and version: how many runs were held for, what settled, what is still reserved, and how many tokens were used.

Per version, deliberately

A version bump changes what an agent costs, so folding versions together would hide the change that explains a bill.

Read total_tokens for consumption, not settled_units

A hold's units are in the unit of the account that paid: tokens for a run your tenant paid for, micro-USD for a run one of your users' wallets paid for. This route sums holds from both, so for an agent with wallet-funded runs settled_units and reserved_units add tokens to money. total_tokens is a token count either way.

Request
curl "$API/v1/usage?project=salmon" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
projectqueryoptionalOne project. Omitted, every project in the tenant.

Responses

StatusMeaning
200{usage}.
401No token, or one that did not verify.
422A project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "usage": [
    {
      "project_slug": "salmon",
      "target_slug": "hotel-concierge",
      "target_version": "1.4.0",
      "holds": 128,
      "settled_units": 412880,
      "reserved_units": 0,
      "total_tokens": 412880
    }
  ]
}

The individual holds

GET/v1/usage/holdsdeploy-service

The reservations behind those totals, one per run segment, newest first — each carrying the invocation id that explains it.

One hold per run, plus one per resume

A run opens a hold when it starts and settles it when it ends. A paused run that is resumed opens a second hold for the resumed turn, so a run can appear more than once here. /v1/usage/invocations/{invocation_id} sums them.

account_id says whose money it was

Your tenant's account is your tenant's own id, and its units are tokens. A wallet's is <tenant>:w:<user>, and its units are micro-USD.

Request
curl "$API/v1/usage/holds?agent=hotel-concierge&minutes=1440" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
limitqueryoptionalDefault 50, clamped to 1–200.
offsetqueryoptionalDefault 0.
projectqueryoptionalOne project. Omitted, every project in the tenant.
agentqueryoptionalOne agent or workflow slug.
minutesqueryoptionalHow far back, in minutes, up to 90 days. 0, the default, is all of it.

Responses

StatusMeaning
200{holds, total}.
401No token, or one that did not verify.
422A project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "total": 128,
  "holds": [
    {
      "hold_id": "hold_5e2a…",
      "invocation_id": "f27bfbb4a1c34e…",
      "account_id": "acme:w:ada",
      "sku": "acme/salmon/concierge",
      "reserved_units": 12000,
      "settled_units": 2186,
      "status": "settled",
      "project_slug": "salmon",
      "target_slug": "hotel-concierge",
      "target_version": "1.4.0",
      "total_tokens": 3433,
      "created_at": "2026-10-14T13:02:11+00:00",
      "expires_at": "2026-10-14T13:17:11+00:00"
    }
  ]
}

What one run cost

GET/v1/usage/invocations/{invocation_id}deploy-service

One run's charge summed across its segments, which models spent it, which tools were charged — and, where it was recorded, the run's status and events.

It needs a hold, so an unbilled agent has nothing here

A target that holds nothing for a run never opens one, and this route answers 404 for its runs. What a run did, as against what it cost, is GET /v1/runs/{invocation_id} on the invocations page.

run and events are additional

They come from the run record, and are null and [] when that record is unavailable — the charge is still answered.

Tenant only

A credential scoped to one project can read a sibling project's run here by its invocation id.

Request
curl "$API/v1/usage/invocations/$INVOCATION_ID" \
  -H "Authorization: Bearer $TOKEN"

Responses

StatusMeaning
200The charge, with run and events.
401No token, or one that did not verify.
404No hold for that id in your tenant — absent, another tenant's, or a run nothing was held for. The three are not told apart.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "invocation_id": "f27bfbb4a1c34e…",
  "hold_id": "hold_5e2a…",
  "account_id": "acme",
  "sku": "acme/salmon/concierge",
  "status": "settled",
  "reserved_units": 12000,
  "settled_units": 3433,
  "segments": 1,
  "project_slug": "salmon",
  "target_slug": "hotel-concierge",
  "target_version": "1.4.0",
  "total_tokens": 3433,
  "created_at": "2026-10-14T13:02:11+00:00",
  "expires_at": "2026-10-14T13:17:11+00:00",
  "tools": [{"tool": "request_late_checkout", "calls": 1,
             "charge_micros": 500, "capped_calls": 0}],
  "usage": [{"model": "gemini-flash-latest", "prompt_tokens": 2925,
             "completion_tokens": 508, "total_tokens": 3433,
             "created_at": "2026-10-14T13:02:14+00:00"}],
  "run": {"status": "finished", "error": null,
          "started_at": "2026-10-14T13:02:11+00:00",
          "finished_at": "2026-10-14T13:02:15+00:00",
          "session_id": "web-9a3f1b2c4d5e"},
  "events": []
}

What your users paid you, over time

GET/v1/analytics/revenuedeploy-service

Your own book: what your end users' wallets were charged for your agents, per bucket, project, agent and SKU, in micro-USD.

Theirs to you, not ours to you

This is money your customers owe you. What the platform charges you is /v1/analytics/cost. Two routes rather than one with a flag, so neither can be mistaken for the other.

The SKU is the name you gave it

Your agent's billing SKU, as declared in its manifest — not the longer form the ledger stores it under.

Request
curl "$API/v1/analytics/revenue?grain=week&project=salmon" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.

Responses

StatusMeaning
200{grain, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "grain": "day",
  "buckets": [
    {"bucket": "2026-10-08T00:00:00+00:00", "project_slug": "salmon",
     "target_slug": "hotel-concierge", "sku": "concierge",
     "micros": 6820, "runs": 5, "tokens": 4201}
  ]
}

What the platform charged you, over time

GET/v1/analytics/costdeploy-service

The platform's charges to you per bucket, project and SKU, in micro-USD — compute, storage and the platform's own metered operations.

Not model tokens

Your model provider bills you for tokens directly, against the key you set as a secret. This series is what the platform itself charges. For a table of the same charges, /v1/cost/summary takes a grain too.

Request
curl "$API/v1/analytics/cost?since=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.

Responses

StatusMeaning
200{grain, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project that could not be a slug.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "grain": "day",
  "buckets": [
    {"bucket": "2026-10-08T00:00:00+00:00", "project_slug": "salmon",
     "sku": "compute.cpu", "sku_name": "CPU reserved", "micros": 108000}
  ]
}

Tokens settled, over time

GET/v1/analytics/tokensdeploy-service

Settled tokens per bucket, project and agent, split into billable input, cached input and output — the counts the charges were computed from.

The three bands stack to the total

input_tokens is already the prompt minus its cached part, because a provider's cached count is a subset of its prompt count. Adding cached_tokens to a raw prompt figure would count a cache hit twice.

Settled runs only

A row exists because a run ended and was priced. A run still in flight has reserved an estimate and settled nothing, so it is not here yet.

Request
curl "$API/v1/analytics/tokens?project=salmon&target=hotel-concierge" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.
targetqueryoptionalOne agent or workflow slug.

Responses

StatusMeaning
200{grain, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no ledger wired, so runs are unbilled. A configuration, not a fault.
502The ledger could not answer. Retry.

Response body

{
  "grain": "day",
  "buckets": [
    {"bucket": "2026-10-08T00:00:00+00:00", "project_slug": "salmon",
     "target_slug": "hotel-concierge", "input_tokens": 14625,
     "cached_tokens": 0, "output_tokens": 2540, "total_tokens": 17165,
     "runs": 5}
  ]
}

Runs over time, succeeded and failed

GET/v1/analytics/invocationsdeploy-service

Runs per bucket, kind and agent, split into succeeded and failed, with their model calls, tool calls, events and tokens.

A run appears once it ends

One still running or paused for a person is not a row yet, and a run whose pod died before it emitted a terminal event never becomes one. These are completed runs, bucketed by when they started.

Request
curl "$API/v1/analytics/invocations?grain=day&kind=agent" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.
kindqueryoptionalagent or workflow. An unknown value matches nothing rather than widening to both.
targetqueryoptionalOne agent or workflow slug.

Responses

StatusMeaning
200{grain, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no analytics warehouse configured. The money series can still work when this does not.
502The warehouse could not answer. Retry.

Response body

{
  "grain": "day",
  "buckets": [
    {"bucket": "2026-10-09T00:00:00+00:00", "kind": "agent",
     "target": "hotel-concierge", "runs": 42, "ok": 39, "failed": 3,
     "llm_calls": 96, "tool_calls": 51, "events": 1180, "tokens": 144180}
  ]
}

Run duration percentiles, over time

GET/v1/analytics/latencydeploy-service

p50, p95 and p99 of run duration per bucket and kind, in milliseconds.

Failures are left out unless you ask

A run that crashed in 200 ms is a fast row and a bad outcome; folded into the percentiles it pulls p50 down, so a spike in failures would read as an improvement. A failed run's duration is time to failure. Pass failures=1 to include them anyway; the failure count is on /v1/analytics/invocations.

Always split by kind

A workflow's duration includes waiting for a person, so one percentile across agents and workflows describes neither.

Request
curl "$API/v1/analytics/latency?kind=workflow&failures=1" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.
kindqueryoptionalagent or workflow. An unknown value matches nothing rather than widening to both.
targetqueryoptionalOne agent or workflow slug.
failuresqueryoptional1, true or yes to include failed runs. Off by default.

Responses

StatusMeaning
200{grain, failures_included, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no analytics warehouse configured. The money series can still work when this does not.
502The warehouse could not answer. Retry.

Response body

{
  "grain": "day",
  "failures_included": false,
  "buckets": [
    {"bucket": "2026-10-09T00:00:00+00:00", "kind": "agent",
     "runs": 39, "p50": 2140, "p95": 7800, "p99": 8522}
  ]
}

Tool calls over time

GET/v1/analytics/toolsdeploy-service

Tool calls per bucket and tool name, with how many runs made them and that tool's own latency percentiles.

timed is how many calls had a measurable duration

A call whose result never arrived is counted and not timed, and a tool that waited for a person's confirmation is left undurated, because its result is on the far side of that wait. Key a chart on timed, not on a percentile being non-zero.

Only runs that called a tool

There is nothing to plot for the others, and counting them under an unnamed tool would invent a series.

Request
curl "$API/v1/analytics/tools?target=hotel-concierge" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
grainqueryoptionalhour, day, week or month; day by default. Anything else is refused rather than defaulted.
sincequeryoptionalISO timestamp, inclusive. Thirty days ago by default. A value with no zone is read as UTC.
untilqueryoptionalISO timestamp, exclusive. Now by default. Half-open, so two adjacent windows never count the same charge twice.
projectqueryoptionalOne project. Omitted, every project in the tenant — whatever project the credential was issued for.
kindqueryoptionalagent or workflow. An unknown value matches nothing rather than widening to both.
targetqueryoptionalOne agent or workflow slug.

Responses

StatusMeaning
200{grain, buckets}.
400An unknown grain, a since or until that is not an ISO timestamp, or an until not after since. The message names the valid grains.
401No token, or one that did not verify.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no analytics warehouse configured. The money series can still work when this does not.
502The warehouse could not answer. Retry.

Response body

{
  "grain": "day",
  "buckets": [
    {"bucket": "2026-10-09T00:00:00+00:00", "tool": "request_late_checkout",
     "calls": 14, "runs": 12, "timed": 14, "p50": 310, "p95": 980, "p99": 1204}
  ]
}

Recent runs, for opening a trace

GET/v1/analytics/runsdeploy-service

The most recent completed runs in the window, one row each, with their outcome, duration, model and tool calls and tokens.

Every run that ended, whether or not money moved

Unlike the holds list, a run that crashed before it settled is here — which is usually the run somebody wants a trace of. A run still going or paused is not, because it has not ended; GET /v1/runs on the invocations page lists those.

Request
curl "$API/v1/analytics/runs?session=web-9a3f1b2c4d5e" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
sincequeryoptionalISO timestamp. Thirty days ago by default.
untilqueryoptionalISO timestamp. Now by default.
projectqueryoptionalOne project. Omitted, every project in the tenant.
kindqueryoptionalagent or workflow. An unknown value matches nothing rather than widening to both.
targetqueryoptionalOne agent or workflow slug.
sessionqueryoptionalOne conversation's runs — the turn that asked, the turns after, a resume somebody approved.
limitqueryoptionalDefault 50, clamped to 1–200.

Responses

StatusMeaning
200{runs}, newest first.
400A since or until that is not an ISO timestamp, or an until not after since.
401No token, or one that did not verify.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no analytics warehouse configured. The money series can still work when this does not.
502The warehouse could not answer. Retry.

Response body

{
  "runs": [
    {
      "invocation_id": "f27bfbb4a1c34e…",
      "started_at": "2026-10-14T13:02:11+00:00",
      "finished_at": "2026-10-14T13:02:15+00:00",
      "duration_ms": 3840,
      "outcome": "finished",
      "error": "",
      "target": "hotel-concierge",
      "version": "1.4.0",
      "kind": "agent",
      "user_id": "eu:ada",
      "session_id": "web-9a3f1b2c4d5e",
      "llm_calls": 2,
      "tool_calls": 1,
      "event_count": 14,
      "prompt_tokens": 2925,
      "completion_tokens": 508,
      "total_tokens": 3433,
      "tools": [{"name": "request_late_checkout", "calls": 1, "ms": [310]}]
    }
  ]
}

One run's trace

GET/v1/analytics/runs/{invocation_id}/tracedeploy-service

The run's row from the list above, plus its recorded event timeline.

The run must have started inside the window

The lookup uses the same since and until as the list, thirty days by default, so an older run is a 404 until you widen the window to include its start.

timeline: false means the events are not available

The run is real and its summary is in run; the event record could not be read, or this deployment keeps none. Not an error.

Tenant only, whatever project says

project narrows the lookup when you pass it and is not checked against the credential, so a credential scoped to one project can read a sibling project's trace by leaving it out.

Request
curl "$API/v1/analytics/runs/$INVOCATION_ID/trace" \
  -H "Authorization: Bearer $TOKEN"

Parameters

FieldTypeDescription
sincequeryoptionalISO timestamp. Thirty days ago by default.
untilqueryoptionalISO timestamp. Now by default.
projectqueryoptionalNarrow the lookup to one project.
kindqueryoptionalagent or workflow. An unknown value matches nothing rather than widening to both.
targetqueryoptionalOne agent or workflow slug.

Responses

StatusMeaning
200{run, events, timeline}.
400A since or until that is not an ISO timestamp, or an until not after since.
401No token, or one that did not verify.
404No such run in your tenant within the window — or one that has not ended yet. Not told apart.
422A project, target or kind that could not be one — a slug, or lowercase letters for kind.
501This deployment has no analytics warehouse configured. The money series can still work when this does not.
502The warehouse could not answer. Retry.

Response body

{
  "run": {"invocation_id": "f27bfbb4a1c34e…", "outcome": "finished",
          "duration_ms": 3840, "target": "hotel-concierge", "…": "…"},
  "timeline": true,
  "events": [
    {"seq": 1, "segment": "", "kind": "started", "payload": {"…": "…"},
     "emitted_at": "2026-10-14T13:02:11.204000+00:00"}
  ]
}

Reading this as a model? llms.txt indexes every page, and each page has a “Copy for AI” control.