Skip to main content
All endpoints sit under /v1/tasks/:taskId/.... taskId is the workspace task UUID (or, for child workflows, parent:step:slug — the controllers split on : where they need the root id). Endpoints group into four families:
  • Lifecycle — what the UI renders and how the user responds (/ui, /snapshots, /action, /row-action).
  • Events — append-only timeline used for reasoning streams and audit (/events).
  • Files — upload, list, download, and provider-tagged ingest under /files.
  • Data ingest — structured JSON payload submission under /data/ingest.

Lifecycle

Combined UI state

Composes getTask + getNextStep from api-workspace into a single UIState payload that ui-tenant can render directly. The container resolves the tenant context from the task’s tenantId, auto-refreshing on cache mismatch — so the dev/e2e wipe-and-reseed flow works without restarting the process. Response (sketch)

Step snapshots

Pure pass-through of api-workspace’s /snapshots endpoint — what was shown + decided at each completed step. Fetched on demand when the user clicks a completed step in the sidebar. Response — Record<string, StepSnapshot> keyed by step id.

Approve / reject

User’s response to an approval gate. Mapped to api-workspace’s /approve or /reject signal endpoint. Body — TaskActionDto:
Response — { "ok": true }.

DATA_TABLE row action

Non-terminal row action — edit_cell or reject_row — forwarded to api-workspace as a user_action signal whose kind is row_action. Workflow handlers drain these via on_row_action (see UI and Temporal signals). Body — TaskRowActionDto:
Response — { "ok": true }.

Events

Append-only timeline of task_events rows. Used for reasoning-stream rendering, audit, and the canvas “what happened next” feed.

Ingest a task event

Internal producer endpoint. When NTRO_INTERNAL_EVENTS_KEY is set, requests must include x-ntro-events-key: <secret> — typically only ntro-worker emits to this endpoint. Body — TaskEventDto:
Response — { "ok": true, "event": <persisted record> }.

List events

Lists persisted events in seq order. No auth — the x-ntro-events-key requirement applies to writes only. Response

Files

All endpoints sit under /v1/tasks/:taskId/files. Bytes live in tenant Postgres (ingest.submitted_documents.data_bytes).

List files for a task

Returns up to 20 documents associated with the task, ordered by upload time descending. Used by the “viewing completed step” mode to find files attached to a previous file-upload step. Filter by source to scope to one runbook source slug. Filtering by taskId keeps the per-source list from leaking duplicate file rows across wipe-and-reseed cycles. Response

Upload a file (browser / script path)

Bytes inline in the request body (typically base64-encoded). NOT advertised to agents in next_step — sandboxed agents often can’t reach this URL. Same persist + signal flow as the agent path. Body — UploadFileDto: Response — UploadResult describing the persisted document + any side effects.

Ingest a file (agent path)

Provider-tagged file reference; api-tenant fetches the bytes server-side. This is what next_step’s submit_file action tells agents to use. Body — IngestFileDto. Same fields as the upload DTO but with fileRef instead of data:
fileRef.provider is one of: The FileFetcher validates per-provider fields. Adding a new provider doesn’t require touching the DTO. Response — UploadResult (same shape as the upload path).

Download

Streams the bytes of a previously-uploaded document. Used by the “viewing completed step” mode to let the user re-download a file submitted earlier. taskId is in the route for symmetry with the upload paths but isn’t enforced at the row level — documentRef is already a UUID. Response — raw bytes with Content-Type from the stored row and Content-Disposition: attachment.

Data ingest

Bulk-oriented endpoint with single-row sugar. Persists rows to ingest.submitted_records and fires a Temporal signal per event after commit.

Body shapes

Two mutually exclusive top-level shapes — exactly one of data / events must be set. Single-row (back-compat):
Bulk:

Field reference

Limits

  • 256 KB per event on the JSON-stringified data; one over-cap event rejects the whole batch.
  • One DB transaction per batch — bulk persists atomically; one Temporal signal fires per event after commit.

Response

The shape mirrors the input:
  • Single body in → single DataIngestResult out.
  • events array in → DataIngestResult[] out.
Each result carries the persisted row id plus any per-event acceptance status the service emitted.

Errors

UI and Temporal signals

How /action and /row-action reach the workflow as Temporal signals.

Ingest outcomes & feedback

Workflow-side handling of submit_file / data_submitted results.