Skip to Content
GuidesThe HTTP API in five minutes

The HTTP API in five minutes

Everything the console and the MCP tools do goes through the daemon’s HTTP API — this guide drives the whole loop with curl: create a source, feed it, read a correlated timeline, define a trigger, watch it fire, and write an observation back. No upstream systems required.

You need a running daemon (Quickstart): navflow up, API at http://127.0.0.1:8787.

Ingest — create a source and feed it

Create a push (webhook) source. The config maps payload fields into the envelope; the label marked primary is the entity key:

curl -s -XPOST localhost:8787/api/sources -H 'content-type: application/json' -d '{ "name": "checkout_probe", "connector": "webhook", "config": { "event_type": "probe", "text_template": "latency {latency_ms}ms on {endpoint}", "labels": [{ "name": "service", "field": "service", "primary": true }] } }' # {"ok":true,"name":"checkout_probe","ingest_key":"webhook-…"}

Feed it:

curl -s -XPOST localhost:8787/ingest/checkout_probe -H 'content-type: application/json' \ -d '{"service": "checkout", "endpoint": "/pay", "latency_ms": 120}' curl -s -XPOST localhost:8787/ingest/checkout_probe -H 'content-type: application/json' \ -d '{"service": "checkout", "endpoint": "/pay", "latency_ms": 1450}' curl -s -XPOST localhost:8787/ingest/checkout_probe -H 'content-type: application/json' \ -d '{"service": "search", "endpoint": "/q", "latency_ms": 45}'

Numeric payload fields (latency_ms) become typed fields triggers can aggregate over; the full payload is kept lossless. This is the generic inbound path for anything that can send JSON.

Locally you can post to the source by name. The response’s ingest_key is the stable, unguessable path (/ingest/<ingest_key>) — use that (plus NAVFLOW_INGEST_TOKEN) when producers deliver over the network.

Read — one correlated timeline

The primary read needs no setup at all — a {label: value} selector across all sources:

curl -s -XPOST localhost:8787/read -H 'content-type: application/json' \ -d '{"selector": {"service": "checkout"}, "window": "15m"}'

You get checkout’s events, time-ordered, from every source that carries the label — with one source it’s modest; the payoff is when logs, metrics, and commits arrive interleaved on one clock.

To fix the source set and reuse it (and to attach triggers), save a view and query through it:

curl -s -XPOST localhost:8787/api/views -H 'content-type: application/json' -d '{ "name": "service_health", "key_field": "service", "sources": ["checkout_probe"] }' curl -s -XPOST localhost:8787/query -H 'content-type: application/json' \ -d '{"view": "service_health", "key": "checkout", "window": "15m"}'

Watch — a trigger that wakes someone

Start a subscriber to be woken (stands in for your agent’s webhook) in a second terminal — examples/woke_receiver.py in the repo listens on http://127.0.0.1:9999/woke. Then define the condition and subscribe it:

curl -s -XPOST localhost:8787/api/triggers -H 'content-type: application/json' -d '{ "name": "slow_checkout", "view": "service_health", "condition": {"aggregate": "max", "field": "latency_ms", "predicate": "> 1000", "window": "5m"}, "emit": {"kind": "slow_checkout", "context_window": "15m"}, "cooldown": "1m" }' curl -s -XPOST localhost:8787/subscribe -H 'content-type: application/json' \ -d '{"trigger": "slow_checkout", "url": "http://127.0.0.1:9999/woke"}'

Cause the condition:

curl -s -XPOST localhost:8787/ingest/checkout_probe -H 'content-type: application/json' \ -d '{"service": "checkout", "endpoint": "/pay", "latency_ms": 2100}'

Within a few seconds the receiver prints the dispatch — with the 15-minute correlated timeline attached. That’s the core move: the store wakes the agent, and the agent starts with context instead of fetching it. Every firing (even with zero subscribers) is logged:

curl -s localhost:8787/api/activity/dispatches

(console: Agents → Trigger dispatches.)

Write back — the agent surface over HTTP

The MCP tools map onto the same endpoints, so you can drive the agent loop by hand. Describe an object — inferred schema, entities, freshness, sample events:

curl -s localhost:8787/catalog/source:checkout_probe

Derive a view the way an agent would (it lands in the catalog tagged with its creator):

curl -s -XPOST localhost:8787/derive -H 'content-type: application/json' -d '{ "sources": ["checkout_probe"], "key_field": "service", "name": "slow_only", "filters": [{"field": "latency_ms", "op": "gt", "value": 1000}]}'

Write an observation back — the first call auto-provisions the agent_memory source, and the memory shows up inside the entity’s timeline on the next read:

curl -s -XPOST localhost:8787/remember -H 'content-type: application/json' \ -d '{"key": "checkout", "content": "latency spikes on /pay correlate with payments deploys"}'

To do all of this from a real agent instead, connect one over MCP — the tool set (read, query, catalog_list / catalog_describe, derive, remember, subscribe, plus the source-setup tools) is this API with discovery built in.

Keep it — the catalog as YAML

Everything you just built is catalog state; YAML is its portable form:

curl -s localhost:8787/api/catalog/export > catalog.yaml # git it, share it

Importing (console → Catalog, or POST /api/catalog/import) supports merge or replace, validated as a whole before anything is written. A fresh daemon pointed at that YAML (NAVFLOW_CATALOG=catalog.yaml navflow up) reproduces the whole setup on first boot.

Last updated on