Ingestion API
The ingestion API is how your systems tell the agent that something happened. Post an event, and every flow attached to it runs.
Everything the agent does starts here. Your systems post an event to the ingestion API, and the agent schedules and runs every published flow attached to that event.
This is the only part of the agent your applications talk to. Flow definitions arrive from the platform, and results go back to the platform, but the trigger comes from you.
Base URL
http://<agent-host>:5002/api/v1
Ingestion listens on port 5002. How you reach it depends on your deployment:
- Docker: the host and mapped port, for example
http://agent.internal:5002/api/v1. - Kubernetes, in-cluster:
http://vaurd-agent-ingestion.vaurd.svc.cluster.local:5002/api/v1. - Kubernetes, from outside: through the ingress you configured, for example
https://agent.example.com/api/v1.
Two other paths are available on the same server. GET /api/v1/healthcheck reports whether ingestion is up, which is useful as a readiness probe. GET /api/v1/swagger/ serves the generated API browser.
Before you can post an event
The event has to exist. Create it in the web application first, under Events, and make sure it has synced to this agent. The agent rejects an event type it does not recognise.
See Events for creating one, and What an event contains for how its parameters are declared.
Post an event
POST /api/v1/ingest Content-Type: application/json
Tells the agent that something happened. The agent records the event, queues it, and returns immediately. Flows run afterwards, in the background, so this call does not wait for them.
Request body
`type` is the important one. It has to match the event's technical name character for character. If no event with that name is registered on the agent, the request is rejected.
`data` is validated against the event's parameters. For each parameter the event declares, the agent checks that a required one is present and that its value has the declared type. Extra fields you send that the event does not declare are accepted and passed through untouched. If the event declares no parameters, data can be omitted.
`id` is documented as optional but should always be sent. The agent uses it when logging a successfully queued event.
`time` is ignored. Whatever you send is replaced with the moment the agent received the event, so events are ordered by arrival rather than by a clock you control.
{
"id": "6f1c2a5e-3d7b-4a19-9c2e-88f0a1b4d5e2",
"type": "order_placed",
"source": "checkout-service",
"specversion": "1.0",
"data": {
"order_id": "A-1001",
"total": 249.99,
"currency": "USD"
}
}curl -X POST http://agent.internal:5002/api/v1/ingest \
-H 'Content-Type: application/json' \
-d '{
"id": "6f1c2a5e-3d7b-4a19-9c2e-88f0a1b4d5e2",
"type": "order_placed",
"source": "checkout-service",
"data": { "order_id": "A-1001", "total": 249.99 }
}'Successful response
{
"id": "0199c8ef-5d88-7895-a52c-40b092b508de",
"status": "QUEUED"
}The id here is not the one you sent. It is the execution event id the agent assigned, and it is what you use to check status later. Store it if you want to follow the run.
When the agent is not ready
If the agent is registered but not currently allowed to process work, the event is still accepted and recorded. It simply waits.
{
"id": "0199c8ef-5d88-7895-a52c-40b092b508de",
"code": "AGENT_NOT_OPERATIONAL",
"status": "QUEUED",
"message": "Agent is blocked currently. Event was ingested but will not be processed until the agent is operational."
}This comes back as 503 Service Unavailable. Treat it as accepted rather than failed. Retrying would create a duplicate, because the first one was already stored. The event is processed once the agent returns to connected.
Errors
Errors share one shape:
{
"statusCode": 400,
"message": "event data validation failed: required field 'order_id' is missing",
"reason": "Bad Request",
"requestId": "..."
}Check an event's status
GET /api/v1/ingest/{id}Returns what happened to an event, including every flow it triggered. The {id} is the execution event id returned by the POST, not the id you sent.
curl http://agent.internal:5002/api/v1/ingest/0199c8ef-5d88-7895-a52c-40b092b508de
{
"id": "0199c8ef-5d88-7895-a52c-40b092b508de",
"eventId": "01a027ab-8000-7cee-86fe-f9a0e178f439",
"name": "order_placed",
"status": "FLOWS_SCHEDULED",
"data": { "order_id": "A-1001", "total": 249.99 },
"executions": [
{
"id": "01a027b1-1111-7000-9000-aaaabbbbcccc",
"flowId": "01a027b2-2222-7000-9000-aaaabbbbcccc",
"versionId": "01a027b3-3333-7000-9000-aaaabbbbcccc",
"flowName": "Order total check",
"versionName": "v3",
"status": "SUCCESS",
"retryCount": 0,
"rootExecutionId": "01a027b1-1111-7000-9000-aaaabbbbcccc",
"createdAt": "2026-09-15T09:12:04Z"
}
],
"createdAt": "2026-09-15T09:12:03Z",
"updatedAt": "2026-09-15T09:12:05Z"
}Event status values
NO_FLOWS_SCHEDULED is worth watching for. It is not an error, and nothing went wrong with your request, but nothing ran either. It usually means the flow you expected has not been published to this agent.
Execution status values
Each entry in executions is one flow run.
The three retry fields describe re-runs scheduled by a rule node. On a first run, retryCount is 0, rootExecutionId equals the execution's own id, and retryNodeId is absent. On a retry, retryCount increments, rootExecutionId still points at the original run, and retryNodeId names the rule that scheduled it. That lets you group an original and all its retries together.
Errors
Using the API well
Post and move on. The call returns as soon as the event is stored and queued, and flow execution is asynchronous. Do not hold a user-facing request open waiting for a result.
Keep your own id. The agent's execution event id is what you need for the status endpoint, so store it against your own record when the POST returns.
Treat 503 as accepted. The event is already stored. Retrying duplicates it.
Poll sparingly, if at all. The status endpoint is there for debugging and reconciliation. For ongoing visibility, the agent's analytics in the web application are the better place to look.