The gateway is an HTTP server that starts and reads runs as one Corbie client. Every request has the header Authorization: Bearer <token>. Every answer is JSON, except a file and a stream, and a refusal is { "error": "<text>" }.
Routes
POST /runsstarts a run from a form; answers { "id": "<id>" }
GET /runslists the gateway's runs in progress, as a JSON list
GET /runs/<id>one run
GET /runs/<id>/recordthe record so far, child runs included: { "entries": […], "run": {…} }
GET /runs/<id>/definitionthe definition the run was started from, as JSON
GET /runs/<id>/files/<path>the bytes of the blob at that path, with its type as Content-Type
POST /runs/<id>/cancelcancels the run: { "life": "10m" }, or an empty body
POST /runs/<id>/eventssends the run an event: { "event": "go", "data": …, "life": "10m" }
POST /runs/<id>/ticketsanswers a ticket: { "ticket": "<the ticket>", "value": …, "life": "10m" }
<id> is the whole ID with its slash, as in /runs/laptop-client/20261013T185126.250Z-571d935912.
Start a run
POST /runs takes multipart/form-data with these parts.
definitionthe definition
file:<path>a file the definition names, at the path it names it by
input:<name>a file that a script reads as the blob input.<name>; its file name sets the type
startJSON with the fields below; it may be left out
inputthe run's input
labels{ "team": "ops" }
allow["net:example.com"]: entries that limit every job of the run and its child runs
denyentries that are refused whatever allow has
timeout"1h": how long the run may take
secrets{ "NAME": "value" }: secrets for this run only
life"10m": how long the start is valid if no controller reads it, default 5m
- A definition can name only the files sent with it.
- A part can be sent as a form field or as a file.
- With an
input:<name>part,inputis an object or absent, with no value under that name.
Query parameters
GET /runs?allincludes runs that have ended
GET /runs?status=failedonly that status: running, done, failed or cancelled
GET /runs?parent=<id>only the child runs of that run
GET /runs?label=team=opsonly runs with that label; label=team matches any value; repeatable
GET /runs?watcha stream of the list
GET /runs/<id>?waitanswers when the run has ended
GET /runs/<id>?wait=30sanswers after 30s at most, with the run as it is then
GET /runs/<id>/record?watcha stream of the record
Answers and status codes
A request to cancel, send an event or answer a ticket stays open until a controller reads the message. life is how long the message is valid, default 5m.
{ "taken": true }the controller acted on the message
{ "taken": true, "acted": false }for an event: whether a rule of the machine matched it
{ "taken": false, "refused": "<reason>" }the controller did not act; the status is 200
400an unknown parameter, field or part, a part sent twice, an unreadable value or a faulty definition
401the token is missing or wrong
404the ID is not a run, the path is not a file of the run, or there is no such route
409the definition or a file of a run that is still waiting
500any other failure, such as a store that cannot be read
504no controller read a cancel, an event or an answer within life
A run that was just submitted is answered as waiting, never with 404.
Streams
A stream is text/event-stream. Each event has a name and one line of JSON.
run{ "run": {…} }: each run in the list, then each that starts, changes or ends
run{ "listed": true }: sent once, after the runs that already existed
entryone entry of the record: those so far, then each as it is written
endthe run, sent once when the run and its child runs have ended
A run event has "new": true the first time a run is sent. A record stream that closes with no end event lost its connection.
Reference
- The gateway starting the gateway, its token and a first run
- Runs the fields of a run and of an entry, a blob's paths, and a blob as another run's input
- corbie start the gateway's flags