Skip to main content
Version: 2.0

Waterline Operator API Reference

Waterline is the durable-state operator surface for both embedded Laravel and standalone-server deployments. The UI uses the same HTTP+JSON API documented here, so scripts, dashboards, and agents can read durable workflow facts without scraping HTML.

Use this reference when you need typed operator evidence: selected-run detail, history export, actionability, command affordances, saved views, preferences, and schedule visibility. Use Monitoring for the conceptual split between Waterline durable state and worker/runtime telemetry.

Installation

Install Waterline in the same embedded Laravel application that installs the workflow package:

composer require \
durable-workflow/waterline:2.0.0 \
durable-workflow/workflow:2.0.1 \
durable-workflow/sdk:2.0.0
php artisan waterline:install

The generated pins select stable 2.x releases of Waterline, Workflow, and the PHP SDK. After upgrading Waterline, publish the current assets:

composer update durable-workflow/waterline
php artisan waterline:publish

For the self-contained service image and its connection, authentication, and persistence inputs, use Monitoring.

Deployment Boundary

Waterline has two backend adapters:

  • Embedded mode runs inside the Laravel host and reads the workflow package's durable state in process.
  • Service mode runs the published Waterline image and reads one standalone server namespace through durable-workflow/sdk and the server's public API.

Both adapters expose the Waterline routes documented on this page. Service mode translates those routes to the corresponding server contracts:

Waterline route familyStandalone-server contract used by service mode
GET /waterline/api/v2/healthServer health, worker registration, and task-queue visibility.
GET /waterline/api/statsThe namespace-scoped operator dashboard and metrics snapshot.
Flow lists, selected-run detail, and history exportWorkflow list, detail, runs, history, and diagnostics from the Server API Reference.
Signal, update, query, cancel, terminate, repair, and archive actionsThe matching server workflow command and repair contracts.
Routes under /waterline/api/v2/schedulesThe server schedule list, detail, history, and mutation contracts.

The server API, CLI, and SDK surfaces remain available directly when Waterline is deployed. Do not assume cross-mode or cross-namespace visibility: runs stay readable and actionable from their owning runtime and namespace. Deployment Modes defines that shared product boundary.

Base Path And Scope

Waterline mounts under the Laravel app's configured Waterline base path. The examples below use /waterline; if your app publishes Waterline under a different prefix, keep the /api/... suffixes the same.

When WATERLINE_NAMESPACE is configured, every list, detail, schedule, and operator-action route is namespace scoped. Cross-namespace reads and commands return not-found semantics instead of leaking another namespace's workflow state.

curl -sS "$APP_URL/waterline/api/instances/order-1001" \
-H "Accept: application/json" | jq '.status, .run_id, .actionability'

Authentication

Every Waterline UI and JSON API controller passes through Waterline's access check. In embedded mode, the Laravel host defines that check and decides which guards, route middleware, gates, policies, SSO/OIDC/SAML sessions, directory-backed groups, service tokens, and rate limits apply.

The current JSON operator API group excludes Laravel's CSRF middleware so a host can apply a session or service-token boundary consistently to both reads and commands. The host remains responsible for authenticating those requests and for documenting any browser-session CSRF protections it adds around the API.

The self-contained service image has no host-application users. Put it behind an authenticating reverse proxy or on a private interface before setting WATERLINE_ALLOW_UNAUTHENTICATED=true; that setting delegates the Waterline front-door check to the surrounding deployment. Separately, WATERLINE_SERVER_TOKEN authenticates Waterline's PHP SDK calls to the standalone server. Never expose that server credential to the browser.

WATERLINE_ACCESS_MODE=read_only blocks mutating Waterline routes locally. operator enables them, but the connected server still applies its own token role and namespace authorization. See Monitoring for the deployment example and the two authentication boundaries.

Dashboard And Health

MethodPathPurpose
GET/waterline/api/statsDashboard totals, backlog counters, repair policy, operator metrics, and fleet trend data.
GET/waterline/api/v2/healthWaterline package/runtime health and v2 data-source readiness.

/waterline/api/stats is the dashboard's summary surface. Treat operator_metrics as Waterline-owned JSON diagnostics, not as a Prometheus scrape surface. Use worker SDK metrics for runtime latency and custom application telemetry.

The Operator Operating Envelope defines how to interpret those diagnostics during rollouts and incident response. In particular:

Field familyMeaning
operator_metrics.backlog.*Durable runnable, delayed, leased, unhealthy, repair-needed, claim-failed, and compatibility-blocked work counts, plus the fleet-level tasks_added_last_minute and tasks_dispatched_last_minute queue-flow facts.
operator_metrics.matching_role.*The node-local matching/dispatch contract for the process serving the request: queue_wake_enabled, deployment shape, task_dispatch_mode, frozen partition_primitives, and current backpressure_model.
operator_metrics.repair.*Repair-loop sweep footprint, including selected candidates, candidate age, and scan pressure.
operator_metrics.projections.*Projection-drift counts for run summaries, waits, timelines, timers, and lineage.
operator_metrics.command_contracts.*Legacy WorkflowStarted contract snapshots that still need backfill.
operator_metrics.history.*History-size and event-count pressure plus continue-as-new recommendations.
queue_visibility.available, queue_visibility.reasonWhether namespace-scoped queue visibility is available on this host app, and the reason when it is not.
queue_visibility.task_queues[].stats.*Queue-local backlog, backlog age, poller counts, workflow/activity ready-versus-leased counts, and per-queue tasks_added_last_minute / tasks_dispatched_last_minute flow facts.
queue_visibility.task_queues[].repair.*Queue-local repair pressure, including candidates, dispatch failures, expired leases, dispatch-overdue counts, and the oldest age for each condition.
coordination_alerts[]Roll-up warnings and errors derived from the health checks plus queue-visibility risks such as backlog without pollers, stale pollers, or aged repair candidates.
checks[], categories.*Blocking versus advisory v2 health checks, with per-check `category = correctness
engine_source, readiness_contractWhether Waterline is actively using the v2 operator bridge and which readiness contract governs that state.

The queue-flow fields answer a specific operator question: is durable queue input arriving faster than the system is dispatching it? tasks_added_last_minute counts distinct durable task rows created in the trailing 60 seconds, and tasks_dispatched_last_minute counts distinct durable task rows whose latest successful dispatch landed in that same window.

Use the queue-flow totals with the server task-queue visibility routes rather than by themselves. Waterline tells you whether durable inflow is outrunning dispatch, while /api/task-queues and /api/task-queues/{taskQueue} tell you whether the hot queue is saturated, intentionally throttled, no_active_workers, or otherwise short on healthy pollers or slots.

GET /waterline/api/v2/health exposes the same queue-local evidence without leaving the Waterline surface. Scripts and dashboards that need one namespace's current queue posture should read queue_visibility.task_queues[] for per-queue stats and coordination_alerts[] for the summary of which queue or health-check condition currently needs operator attention.

The matching_role fields answer a different question: which matching shape is this node currently serving? shape distinguishes in_worker from dedicated, partition_primitives freezes the routing axes as connection/queue/compatibility/namespace, and backpressure_model currently reports lease_ownership. Treat that block as process-local. During mixed-shape rollouts, compare it across nodes before assuming backlog or poll differences mean worker trouble.

GET /waterline/api/v2/health uses the same distinction: error is blocking, warning is advisory, and ok means the current v2 operator bridge is ready.

List Views

List views are bucketed by durable status:

MethodPathBucket
GET/waterline/api/flows/runningOpen or actively blocked runs.
GET/waterline/api/flows/completedRuns closed successfully, including continued runs with closed_reason = continued.
GET/waterline/api/flows/failedFailed runs.
GET/waterline/api/flows/cancelledCancelled runs.
GET/waterline/api/flows/terminatedTerminated runs.

List rows are compact operator summaries. Stable fields include workflow identity (id, instance_id, run_id, workflow_type), state (status, closed_reason, archived_at), timing, history_event_count, history_size_bytes, continue_as_new_recommended, and repair/actionability badges such as repair_blocked.

Selected-Run Detail

Waterline has two addressing modes:

MethodPathPurpose
GET/waterline/api/instances/{instanceId}Current selected run for a workflow instance.
GET/waterline/api/instances/{instanceId}/runs/{runId}Explicit selected run.
GET/waterline/api/flows/{id}Legacy/detail lookup by Waterline row or run id.

Selected-run detail is the authoritative JSON contract for operator screens. It contains durable state and derived diagnostics for:

Field familyMeaning
activities, timers, waits, childrenCurrent and historical wait state rebuilt from typed history first.
signals, updates, declared_signals, declared_updates, declared_queriesCommand lifecycle rows plus loadable workflow contract targets.
timelineOrdered durable events and diagnostic entries.
exceptions, logsFailure facts and replay/debug context.
can_signal, can_update, can_query, can_cancel, can_terminate, can_archiveUI and automation affordances for the selected run.
actionabilityVersioned repair and evidence contract described below.

Automation should prefer selected-run detail over visual screenshots. A screenshot can show what an operator saw; selected-run detail explains why a workflow can or cannot be repaired, queried, cancelled, archived, or replayed.

History Export

History exports are replay/debug bundles. They intentionally include stored workflow, command, activity, update, task, failure, and history payloads so a developer can reproduce or archive the selected run.

MethodPathPurpose
GET/waterline/api/instances/{instanceId}/history-exportExport the current selected run for an instance.
GET/waterline/api/instances/{instanceId}/runs/{runId}/history-exportExport an explicit run.
GET/waterline/api/flows/{id}/history-exportLegacy/detail export by Waterline row or run id.

If an export can leave a protected environment, configure the workflow history-export redactor first. Downstream tools should preserve the export's redaction metadata so reviewers can tell which policy shaped the artifact.

Actionability Contract

Waterline annotates list rows, selected-run detail responses, timeline entries, and history exports with the versioned actionability contract:

{
"actionability_contract": {
"schema": "waterline.actionability",
"version": 1
}
}

The contract identifier is actionability_contract.schema = waterline.actionability with actionability_contract.version = 1.

Run-level actionability answers whether the selected run can be repaired:

FieldMeaning
repair_stateOne of repairable, blocked, not_needed, or unknown.
repairableBoolean shorthand for repair_state = repairable.
blocked_reasonStable reason code when repair_state = blocked.
status_bucketThe Waterline bucket that shaped the run-level decision.
closed_reasonDurable close reason when the run is closed.
task_problemWhether Waterline saw a task-level problem on the run.
diagnostic_only_evidenceTrue when at least one row is informative but not a resume source.

Evidence rows under activities, waits, timers, exceptions, logs, and timeline/export entries can include their own actionability block:

FieldMeaning
stateactionable when the row is a valid repair source, otherwise diagnostic_only.
repair_sourceTrue only for rows backed by a repairable source authority.
diagnostic_onlyTrue when the row must not be used as a resume source.
history_authoritySource authority such as typed_history, mutable_open_fallback, failure_row_fallback, or unsupported_terminal_without_history.
history_unsupported_reasonStable reason code for unsupported fallback history.

Agents and scripts must gate repair/resume decisions on actionability.repair_state, actionability.repairable, and row-level actionability.repair_source. A row with diagnostic_only = true is evidence, not permission to replay or resume.

Operator Actions

Waterline actions are durable commands issued through the selected-run contract. Instance routes target the current run; run routes reject stale or wrong-run targets explicitly.

MethodPathPurpose
POST/waterline/api/instances/{instanceId}/queries/{query}Execute a declared query against the current run.
POST/waterline/api/instances/{instanceId}/signals/{signal}Send a signal to the current run.
POST/waterline/api/instances/{instanceId}/updates/{update}Submit an update to the current run.
POST/waterline/api/instances/{instanceId}/repairDispatch a repair pass for the current run when actionability allows it.
POST/waterline/api/instances/{instanceId}/cancelRequest cancellation for the current run.
POST/waterline/api/instances/{instanceId}/terminateTerminate the current run.
POST/waterline/api/instances/{instanceId}/archiveArchive the selected closed run.
POST/waterline/api/instances/{instanceId}/runs/{runId}/queries/{query}Execute a query against an explicit selected run.
POST/waterline/api/instances/{instanceId}/runs/{runId}/signals/{signal}Send a signal only if the selected run is current.
POST/waterline/api/instances/{instanceId}/runs/{runId}/updates/{update}Submit an update only if the selected run is current.
POST/waterline/api/instances/{instanceId}/runs/{runId}/repairRepair an explicit selected run.
POST/waterline/api/instances/{instanceId}/runs/{runId}/cancelCancel only if the selected run is current.
POST/waterline/api/instances/{instanceId}/runs/{runId}/terminateTerminate only if the selected run is current.
POST/waterline/api/instances/{instanceId}/runs/{runId}/archiveArchive the selected closed run.

Signals, updates, and queries accept JSON arguments. Invalid arguments return field-level validation failures. Replay blocks return 409 Conflict with a stable reason such as workflow_definition_unavailable instead of attempting best-effort execution.

Update Inspection

MethodPathPurpose
GET/waterline/api/instances/{instanceId}/updates/{updateId}Inspect an update lifecycle row for the current run.
GET/waterline/api/instances/{instanceId}/runs/{runId}/updates/{updateId}Inspect an update lifecycle row for an explicit run.
GET/waterline/api/flows/{id}/updates/{updateId}Legacy/detail update lookup.

Use update inspection when a UI or agent needs to explain whether an update is accepted, applied, completed, rejected, timed out while waiting, or blocked by replay compatibility.

Schedules

Waterline schedule routes are v2 visibility and operator-action routes:

MethodPathPurpose
GET/waterline/api/v2/schedulesList schedules visible in the current namespace.
GET/waterline/api/v2/schedules/{scheduleId}Describe one schedule.
POST/waterline/api/v2/schedules/{scheduleId}/pausePause future fires.
POST/waterline/api/v2/schedules/{scheduleId}/resumeResume a paused schedule.
POST/waterline/api/v2/schedules/{scheduleId}/triggerTrigger an immediate fire.
POST/waterline/api/v2/schedules/{scheduleId}/backfillBackfill a time window.
DELETE/waterline/api/v2/schedules/{scheduleId}Delete a schedule.

Schedule responses expose action, status, next fire, recent fire history, overlap policy, note, memo, and search attributes for operator review.

Saved Views And Preferences

Saved views and preferences are UI-owned operator configuration, not workflow history. They are still useful for stable runbooks because they let teams share the exact filters and table layout used during an incident.

MethodPathPurpose
GET/waterline/api/saved-viewsList saved operator views.
POST/waterline/api/saved-viewsCreate a saved view.
GET/waterline/api/saved-views/{view}Read one saved view.
PUT/waterline/api/saved-views/{view}Update a saved view.
DELETE/waterline/api/saved-views/{view}Delete a saved view.
GET/waterline/api/preferences/{surface}Read UI preferences for one surface.
PUT/waterline/api/preferences/{surface}Update UI preferences for one surface.

Do not treat saved-view names or preference payloads as durable workflow facts. For evidence, cite selected-run detail or history export.

Error Contract

Waterline uses ordinary HTTP status codes and JSON error details:

StatusMeaning
400Malformed request or unsupported action payload.
404Workflow instance, run, update, schedule, saved view, or preference surface was not found in the current namespace.
409The selected run cannot execute the action, often because it is historical, closed, replay-blocked, or definition-unavailable.
422Validation failed; response includes field-level errors.
500Unexpected application failure.

Automation should branch on status plus stable fields such as blocked_reason, query_blocked_reason, outcome, reason, and actionability values. Do not parse toast text or button labels as the contract.

See Also