Skip to main content
The Runflow runtime API is callable two ways:
  1. From SDK code — use createRunflowAPIClient() (and the higher-level Reviews / Memory / Knowledge modules built on top of it).
  2. From any HTTP client — talk to the runtime endpoints directly, e.g. from a service that doesn’t run the SDK.
This page covers both — the SDK exports first, then the raw REST surface.

SDK API Client

The factory follows a config priority: explicit options → 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 the x-api-key header (or as a Bearer token in Authorization):
Get an API key from the portal under Settings → API Keys. Each key is tenant-scoped; the platform derives 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

The runtime surface lives under the /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’s Reviews class wraps these endpoints — use it from agent code unless you need raw HTTP.

Create a review

Each execution can only have one review. A second POST returns 409 Conflict. Use the exists endpoint below for an idempotent check.

Check if an execution already has a review

Response: { "exists": true, "review": { "id", "rating", "status", "comment", "createdAt" } }.

List reviews

Query params (all optional):

Get a single review

Update a review

Partial update — send only the fields you want to change. Allowed fields: status, actionTaken, resolutionNotes, correctedOutput, comment, priority, tags. Setting status: "resolved" auto-stamps resolvedBy and resolvedAt.

Delete a review

Hard delete.

Stats

agentId is required. Response: { total, pending, inProgress, resolved, badReviews, needsImprovement, critical, highPriority, avgResolutionHours }.

Export for training

Returns an array of OpenAI conversational fine-tuning examples — one per matching review, with the correctedOutput substituted into the assistant turn when present.
Typical filter: { 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

Used by the SDK’s 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

Most-recent-first list of events for an agent. Useful for debugging emissions, building external “live event” widgets, or sanity-checking that track() calls landed. Query params: Response:

Query events (raw or grouped)

Table-style query against the event store. Two modes:
  • 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.
The KPI-card style standalone aggregate (one number per query — sum/avg/count/rate of a metric) remains portal-only for now; this endpoint is for the table-shaped reads. Body: Response:
Example — raw mode for a backfill job:
Example — aggregate mode for a “sales by category” table:

List dashboard cards

Returns every card configured for the agent, with its 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

Idempotent on (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

Returns the tabs configured for the agent, ordered by sortOrder ASC.

Upsert a dashboard tab

Idempotent on (agentId, name). This is the endpoint metrics.defineTab(...) → metrics.sync() (SDK) and rf metrics sync (CLI) call.
Response: { "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 of amount 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_events covers exactly this shape).
  • Or use the REST events/query endpoint with mode: '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’s Knowledge.ingestFile (SDK ≥ 1.3.2) and rf kb upload (CLI ≥ 0.3.22) wrap these endpoints.

Start an ingestion

Form fields: 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

Returns { "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