Every endpoint lives under https://api.fous.com/v1. Requests and responses are JSON, and every /v1 endpoint takes your API key as a bearer header. The exact contract is OpenAPI 3.1; the API reference is generated from it.
GET reads take query parameters, POST does work and takes a JSON body of at most 4 MB, and IDs go in the path. Fields your request doesn't send take their defaults; an unknown body field answers 400 invalid_request with the reason.
Slow work
Runs, builds and workflow runs can outlast a single HTTP request, so they answer in one of two ways: 200 when the work ended in time, or 202 with its id while it goes on. Work that answers 202 keeps going whether or not you hold on.
POST /v1/runs,POST /v1/buildsandPOST /v1/workflows/{id}/runstakewaitin the body, in seconds from 0 to 60: 30 by default for runs, 0 for builds and workflow runs.GET /v1/runs/{id},GET /v1/builds/{id},GET /v1/connections/{id},GET /v1/methods/{domain}/{name}andGET /v1/workflows/{id}/runs/{run_id}take?wait=60(0 to 60 seconds) and hold the answer until the work moves on or the time passes.POST /v1/runs/{id}/cancel,POST /v1/builds/{id}/cancelandPOST /v1/workflows/{id}/runs/{run_id}/cancelstop the work and answer with the updated resource. A method run stopped midway is free; a workflow run keeps the cost of the steps it had already finished.
Every POST /v1/runs is new, charged work unless you send an Idempotency-Key (Retry safely). Keep wait below your HTTP client's timeout, and read a slow run by its id instead of sending the request again.
Pagination
GET /v1/runs returns { "runs": [...], "has_more": true }, newest first. limit is 1 to 100 (20 by default). For the next page, send the last run's id (or an ISO time) as before. GET /v1/builds and GET /v1/workflows/{id}/runs work the same way:
Streaming
POST /v1/workflows and PATCH /v1/workflows/{id} send Server-Sent Events while the AI writes when you ask with Accept: text/event-stream.
Retries
A failure answers an HTTP status and an error object with retryable where it applies (Errors). On 429 rate_limited and 503, wait for the Retry-After header (or error.retry_after, in seconds) before trying again. A POST /v1/hooks/{token} call is safe to repeat with the same Idempotency-Key. So is a run sent with one; without it, a retry is a new run. Check first when a failure says may_have_run: true.
Every response has an X-Request-Id; a failure repeats it as error.request_id. Quote it to support, along with the code, never a key.