- From SDK code — use
createRunflowAPIClient()(and the higher-levelReviews/Memory/Knowledgemodules built on top of it). - From any HTTP client — talk to the runtime endpoints directly, e.g. from a service that doesn’t run the SDK.
SDK API Client
rf.json → env vars → defaults. The resulting client exposes typed methods for chat, chatStream, vectorSearch, connector, memory.*, documents.*, prompts.*, and reviews.* (since SDK ≥ 1.1.13).
Higher-level modules — Reviews, Memory, Knowledge, RAG, LLM — wrap this client with stricter argument validation and typed errors. Prefer them in agent code; reach for the raw client only when you need something the modules don’t cover.
Authentication
All runtime endpoints accept an API key in thex-api-key header (or as a Bearer token in Authorization):
tenantId from the key and applies it to every query.
The reviewedBy / updatedBy audit fields on execution reviews are auto-populated from the API key label — name your keys descriptively (e.g. qa-bot, nightly-export) so the audit trail is readable.
Base URL
/api/v1/runtime/v1/observability/... prefix. Paths below are shown relative to the base URL.
Execution Reviews
CRUD + stats + training-data export for the execution-review feedback loop. The SDK’sReviews class wraps these endpoints — use it from agent code unless you need raw HTTP.
Create a review
POST returns 409 Conflict. Use the exists endpoint below for an idempotent check.
Check if an execution already has a review
{ "exists": true, "review": { "id", "rating", "status", "comment", "createdAt" } }.
List reviews
| Param | Type | Description |
|---|---|---|
agentId | string | Filter by agent. |
status | enum | pending_review, in_progress, resolved, wont_fix. |
rating | enum | good, bad, needs_improvement. |
priority | enum | low, medium, high, critical. |
dateFrom / dateTo | ISO 8601 | Date range. |
search | string | Portuguese full-text search across comments. |
limit | number | Default 50, capped at 100. |
offset | number | Pagination offset. |
Get a single review
Update a review
status, actionTaken, resolutionNotes, correctedOutput, comment, priority, tags. Setting status: "resolved" auto-stamps resolvedBy and resolvedAt.
Delete a review
Stats
agentId is required. Response: { total, pending, inProgress, resolved, badReviews, needsImprovement, critical, highPriority, avgResolutionHours }.
Export for training
correctedOutput substituted into the assistant turn when present.
{ agentId, status: 'resolved' } to pull only human-reviewed and corrected examples.
Dashboards & Events
The pieces of the metrics pipeline that are exposed to API-key callers (SDK, CLI, server-to-server):Ingest events
track() and CLI tools to push raw events. The events are written async (fire-and-forget) and become queryable within a few seconds.
tenantId and agentId are derived from the API key — you don’t need to pass them.
Recent events feed
track() calls landed.
Query params:
| Param | Type | Description |
|---|---|---|
agentId | string | Optional. Defaults to the agent bound to the API key. |
eventName | string | Optional filter. |
limit | number | Default 50, capped at 100. |
offset | number | Pagination offset. |
Query events (raw or grouped)
mode: 'raw'(default) — returns individual events with the columns you ask for. Use for backfill jobs, exports, or anything that needs the underlying rows.mode: 'aggregate'— groups rows by a single property key and applies one or more metrics (count,sum,avg,min,max). Use for table-shaped reports.
| Field | Type | Description |
|---|---|---|
agentId | string | Optional. Defaults to the API-key agent. |
eventName | string | Required. |
mode | 'raw' | 'aggregate' | Default 'raw'. |
columns | string[] | (raw mode) Property keys to project. Omit for all. |
groupBy | string | (aggregate mode) Property key to group on. |
metrics | Array<{ aggregation, propertyKey?, alias }> | (aggregate mode) One per output column. aggregation is one of count, sum, avg, min, max. |
filters | Array<{ propertyKey, operator, value }> | Operators: eq, neq, gt, lt, gte, lte, contains, in. |
dateFrom / dateTo | ISO 8601 | Date range. |
sortBy / sortOrder | string / asc | desc | Result ordering. |
limit / offset | number | Pagination. |
List dashboard cards
cardType, config, and gridLayout. Useful for read-only views of what’s published, or for snapshotting a dashboard into version control.
Upsert a dashboard card
(agentId, eventName, cardType, aggregation, propertyKey). This is the endpoint metrics.sync() (SDK) and rf metrics sync (CLI) call under the hood — you can call it directly from server-to-server jobs.
cardType must be one of number, rate, line, bar, pie, table, funnel, gauge. The per-type config shape is validated server-side; see the portal Metrics tab for the canonical UI.
List dashboard tabs
sortOrder ASC.
Upsert a dashboard tab
(agentId, name). This is the endpoint metrics.defineTab(...) → metrics.sync() (SDK) and rf metrics sync (CLI) call.
{ "success": true, "created": true, "id": "tab-uuid", "tab": { ... } }. created is false on subsequent calls with the same name; if sortOrder is provided and differs, it gets updated.
Aggregating event values via MCP
KPI-style aggregation (single number —sum, avg, count, rate, distinct_count, group_by) is not exposed over REST, but it’s available to MCP-compatible clients (Claude, Claude Code, Cursor, anything connecting through the public MCP connector) via three tools:
| Tool | Scope | What it does |
|---|---|---|
aggregate_events | mcp:read | Single-number KPI or time/category series. Supports dateGrouping for time series and group_by for distributions. |
query_events | mcp:read | Table-style read — mode='raw' for individual rows, mode='aggregate' with groupBy + metrics for grouped reports. |
render_dashboard_card | mcp:read | Pass a cardId and get back the current rendered value, dispatching on the card’s cardType and config. Supports number / rate / line / bar / pie / gauge / table / funnel. |
events/query and events/feed (which are REST), but add the standalone aggregate that REST doesn’t cover. See MCP → Available MCP Tools for the full catalogue.
What’s still portal-only
Over REST, the KPI-style standalone aggregate (e.g. “sum ofamount where category = electronics for the last 7 days”) and the discovery endpoints (get_event_names, get_event_properties, property-values) remain behind Auth0JwtGuard. If you need them server-to-server today:
- Use MCP (
aggregate_eventscovers exactly this shape). - Or use the REST
events/queryendpoint withmode: 'aggregate'+groupBy— the same numbers come back as rows.
Errors
The runtime API uses standard HTTP status codes:| Status | Meaning |
|---|---|
400 | Invalid input — usually a Zod/DTO validation failure. The body has a message array. |
401 | Missing / invalid API key. |
403 | API key is valid but lacks access to the requested resource (wrong tenant, disabled scope). |
404 | Resource not found. For reviews, this also fires when the ID belongs to another tenant. |
409 | Conflict — for execution reviews, the execution already has one. |
422 | Semantic validation error (e.g. comment shorter than 10 chars). |
5xx | Server error. Safe to retry with backoff. |
Next Steps
Reviews module
Typed SDK wrapper for these endpoints
Observability Guide
Tracing, metrics, and the review feedback loop