- 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
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:
Response:
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.
Response:
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:
These mirror the runtime endpoints
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.
Knowledge Ingestion (async)
Background ingestion for large knowledge-base files (50k-row catalogs, big documents). The upload returns immediately with a job id; batched embedding runs server-side with checkpoint resume. The SDK’sKnowledge.ingestFile (SDK ≥ 1.3.2) and rf kb upload (CLI ≥ 0.3.22) wrap these endpoints.
Start an ingestion
CSV files are ingested one document per row. Response is
202 Accepted:
Poll a job
status transitions queued → processing → completed | failed. documentId is set on completion; error on failure. Ingestion resumes from a checkpoint if the worker restarts mid-job.
List a store’s jobs
{ "success": true, "vectorStore": "...", "jobs": [ ...job objects... ] }, newest first (default limit 50, max 100).
Errors
The runtime API uses standard HTTP status codes:
Error responses share this shape:
Next Steps
Reviews module
Typed SDK wrapper for these endpoints
Observability Guide
Tracing, metrics, and the review feedback loop