From a sentence
Send prompt. Fous reads your methods, picks the ones the request needs, wires their inputs and writes the steps between them.
Returns 200 with the saved workflow, disabled, plus an ai object describing what the AI built (a definition sent instead returns 201). timezone (optional) sets the time zone for times like "9am"; without it, schedules use UTC.
The response also includes definition. The AI uses only your organization's methods and the inputs their contracts accept. An email step goes to the person making the request unless the prompt names other addresses; with an API key there is no person, so to is left empty.
A value the AI cannot know, such as a webhook URL you did not provide, is left empty and listed in incomplete. When a choice has a sensible default, the AI uses it and says so in summary.
Until each value is set with PATCH /v1/workflows/{id}, the workflow cannot run or be enabled: both return 409 conflict with reason: "workflow_incomplete", the incomplete values and any pending steps.
When the AI asks or replies instead
If a step needs a website or account the AI cannot determine ("our supplier portal", "our bank"), the AI asks instead of building. Nothing is saved, and the response is 200 with workflow: null:
To answer, send the conversation as messages, newest last, ending with the person's answer:
A prompt that requests no automation ("what can you do?") also saves nothing and returns 200 with workflow: null and the answer in ai.reply. If the AI is unavailable, the response is 503 service_unavailable and nothing is saved.
Watch it being written
With Accept: text/event-stream, the same request returns Server-Sent Events while the AI writes, so you can render the workflow step by step.
Events are sent as they happen:
| Event | Data |
|---|---|
status | { text }: a short description of what the AI is doing. |
question | { text, options, placeholder, allow_other }: the reply asks the person to choose. |
reply | { text }: the next piece of a reply, when the AI replies instead of building. |
workflow | { name, description }, as soon as they are written. |
trigger | { trigger }. |
step | { index, step }. Emitted as each top-level step is completed, in order. Loops are emitted with all nested steps included. |
reset | {}. The initial draft failed validation and the AI is restarting; discard earlier streamed events. |
done | The result, the same body as the JSON response: the workflow with ai, or { workflow: null, ai }. |
error | The error object, as in a JSON response. |
A step in a step event may not have its key yet; the definition in done has them all.
From a definition
POST /v1/workflows also accepts { name, description, definition, enabled }, as in the example workflow. A definition is a trigger and a list of steps. A body with prompt or messages is drafted by the AI; any other body is saved as sent.
Fous validates the definition against your methods. An invalid definition returns 400 invalid_request listing all validation errors and their paths:
A definition is at most 200 KB. A method step must name one of your methods by its slug and use only that method's inputs. Templates and transform code can read only the trigger, earlier steps and, inside a loop, the current item.
Build missing methods
If a request needs a site your organization has no method for, the AI still writes the whole workflow. In place of the missing method it adds a pending step: method is null, and pending gives what the method should do (need), the site to build on, and the request sent to the builder (build_prompt). Later steps read its output using field names inferred from the need, and the step is listed in ai.missing.
While a step is pending, the workflow is saved but cannot run or be enabled: both return 409 conflict with reason: "workflow_incomplete" and the pending steps. To build the method and set its site in one request:
Returns 202 with build_id. This is an ordinary build, subject to your plan's limits. The body is optional:
| Field | Meaning |
|---|---|
site | The website to build on, as a domain or sign-in URL. Replaces the step's site. Saved only when the build starts, so a refused build changes nothing. |
connections | IDs of the connected accounts the build may use. |
pending.status changes to building. Poll GET /v1/workflows/{id} every few seconds. When the build ends, the step runs the new method: Fous fills its input from the method's contract and updates later steps to read its real output.
- A failed build sets
pending.statustofailedwith areason. Call the endpoint again to retry. - A step with no site and no
sitein the request returns409withreason: "site_required". - A step that is already building returns its
build_id. Sending a differentsitefor it returns409 conflict. - To remove a step, pending or not, call
DELETE /v1/workflows/{id}/steps/{key}. What read its output reads nothing: templates are emptied, a filter drops conditions about it, and a transform whose code read it gets new code (a transform with code and no instruction is not rewritten: the removal answers400naming it, so change its code first). A value left empty is listed inincomplete.
Change a workflow
PATCH /v1/workflows/{id} updates any of name, description, definition and enabled. A new definition is validated as above and replaces the old one entirely. Enabling a workflow that is not ready returns 409 with reason: "workflow_incomplete". DELETE /v1/workflows/{id} deletes a workflow; its runs stay readable. GET /v1/workflows lists workflows, most recently changed first.
Change it with the AI
Send PATCH /v1/workflows/{id} with prompt, or the conversation so far as messages, newest last, and the AI changes the workflow and saves it:
The response is the saved workflow with ai, as when creating from a sentence:
The AI keeps everything you did not ask to change and reads the last 12 messages. A question, or the AI asking one back, changes nothing: the answer is the workflow as it is, with ai.summary null and its words in ai.reply (or ai.question). With Accept: text/event-stream the response streams as above, and done carries the same body.
A change is saved with the same checks as any PATCH, and a refused change saves nothing: 400 invalid_request, 403 plan_limit, or 409 with reason: "workflow_incomplete" when the workflow is enabled and the change leaves it not ready. If the AI's answer does not hold after a retry, the response is 422 invalid_input with reason: "ai_failed".
Add "preview": true to see the change without saving it: the response is the workflow as it would be, and name and definition in the request are the draft the AI reads. Send it back with PATCH to keep it.
The AI costs no credits within your plan's AI messages.