Serving an HTTP Endpoint
This tutorial is the inbound counterpart to Polling An HTTP API:
a job that listens for HTTP requests with the
http-server input, processes each
request as an event, and — when the caller needs a real answer — returns an
explicit status and body with the
response-complete output.
1. Accept requests
Section titled “1. Accept requests”A minimal listener binds an address and path and emits one event per request:
input: http-server: address: 127.0.0.1:8085 path: /v1/ingest json: true source-ip-field: client_ipjson: trueparses the request body as JSON into the event.pathrestricts the listener to one route; requests elsewhere are not accepted.source-ip-fieldrecords the caller address for auditing.
2. Choose a response mode
Section titled “2. Choose a response mode”By default the listener acknowledges requests immediately (immediate mode):
the caller gets a quick acceptance while the pipeline processes the event
asynchronously. That is the right shape for fire-and-forget ingestion.
When the caller must learn the outcome — a webhook that needs a meaningful
status code, an API that returns a computed result — switch to
wait-for-workflow and bound the wait:
input: http-server: address: 127.0.0.1:8085 path: /v1/ingest json: true response: mode: wait-for-workflow timeout-seconds: 8 timeout-status-code: 503 timeout-body: '{"error":"processing timeout"}' body-max-bytes: 65536The request now stays open until the event reaches a response-complete
output or the timeout fires. Pick timeout-seconds from the caller’s
patience, not your processing hopes: many webhook providers fail a delivery
after about 10 seconds and do not automatically retry it, so answering by 8
seconds — even with a 503 — leaves margin and keeps the failure visible on
their side.
3. Answer every outcome explicitly
Section titled “3. Answer every outcome explicitly”In wait-for-workflow mode, every event from the listener must reach a
response-complete output. Compute the outcome, set the status and body as
fields, and finish:
actions: - java-script: source: | function transform(event) { if (!event.json || typeof event.json !== "object") { event.response_status = 400; event.response_body = JSON.stringify({ error: "malformed payload" }); return event; } if (event.json.type !== "order.created") { event.response_status = 204; event.response_body = ""; return event; } // ... durable handling of the accepted event goes here ... event.response_status = 202; event.response_body = JSON.stringify({ accepted: true }); return event; }
output: response-complete: status-code-field: response_status content-type: application/json body: field: field: response_bodyThis single-job shape returns a different status per outcome — for example
202 accepted, 204 ignored, 400 malformed — from one terminal output. A
common four-lane contract for authenticated webhooks adds 401 for a failed
authentication check, decided before the payload is parsed or acted on.
Two more rules keep the contract honest:
- Answer
202only after the work is durable. If acceptance means “queued for processing”, complete the response after the durable handoff succeeds — not before — so a crash cannot acknowledge work that was lost. If the handoff fails, let the timeout return503: the caller’s delivery record then correctly shows a failure to retry or investigate. - Expect replays. Webhook deliveries can repeat or arrive out of order. Deduplicate on a stable identity from the payload (an event or run ID), not on the delivery attempt.
In a multi-job workflow, the same rules apply per branch: route outcomes with
conditional dispatch (see Routing and Fan-out)
and terminate every lane — accepted, ignored, rejected — in its own
response-complete. The synchronous-response context travels with the event,
and on-missing-context: ignore lets a shared tail also serve events that
did not originate from a waiting caller.
4. Test with Run & Trace, then deploy
Section titled “4. Test with Run & Trace, then deploy”- Run the job and send a request:
curl -i -X POST 127.0.0.1:8085/v1/ingest -d '{"type":"order.created"}' - Confirm each outcome returns its intended status, and that an intentionally slow or dropped event returns the timeout status — before a real caller finds out for you.
- Stage and deploy per Deploying jobs, pinning the job to the worker your proxy targets (see Placement and Scaling).
Where to go next
Section titled “Where to go next”http-serverreference for all listener fields, including TLS.response-completereference for header, content-type, and body sources.- Triggers for the curated run-now registry and its synchronous-response contract.
- Delivery Semantics for acknowledgement and replay boundaries.