# Fous documentation Every page of https://docs.fous.com, in reading order. Source: https://docs.fous.com/llms.txt # Fous documentation > Call any website as a workflow from your code or your AI agent. One request in, structured data out. Source: https://docs.fous.com/ - [Quickstart](https://docs.fous.com/quickstart.md): your first call in five minutes - [Call a workflow](https://docs.fous.com/guides/typed-operations.md): the request and response contract - [Connect an AI agent](https://docs.fous.com/guides/mcp.md): Claude, Codex, Cursor and any MCP client - [API reference](https://docs.fous.com/api-reference.md): every endpoint ## Your first call A workflow is a website task with a typed input and output. Name the workflow, its operation and the input, and Fous runs it and returns the data. This call reads the Hacker News front page; it needs an [API key](https://docs.fous.com/authentication) and nothing else. **cURL** ```bash curl 'https://api.fous.com/v1/query' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Idempotency-Key: $FOUS_IDEMPOTENCY_KEY" \ -H 'Content-Type: application/json' \ -d '{"api":"@hacker-news","operation":"list_front_page","input":{"list_name":"show_hn","max_results":5}}' ``` **Node.js** ```javascript const response = await fetch('https://api.fous.com/v1/query', { method: 'POST', headers: { Authorization: `Bearer ${process.env.FOUS_API_KEY}`, 'Idempotency-Key': crypto.randomUUID(), 'Content-Type': 'application/json', }, body: JSON.stringify({ api: '@hacker-news', operation: 'list_front_page', input: { list_name: 'show_hn', max_results: 5 } }), }); const result = await response.json(); if (!response.ok) throw new Error(`${result.error.code}: ${result.error.message}`); console.log(result.data.output); ``` **Python** ```python import os import requests import uuid response = requests.post( "https://api.fous.com/v1/query", headers={ "Authorization": f"Bearer {os.environ['FOUS_API_KEY']}", "Idempotency-Key": str(uuid.uuid4()), }, json={ "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 } }, timeout=180, ) result = response.json() if not response.ok: raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}") print(result["data"]["output"]) ``` The response carries the output and a receipt. Each completed run costs 1 credit; finding workflows and checking status is free. ```json { "success": true, "data": { "output": { "stories": [ { "rank": 1, "title": "Show HN: Jeff – Jev-compatible 0.8B decision models, trained at home", "author": "firelex", "points": 230, "comment_count": 79, "discussion_link": "https://news.ycombinator.com/item?id=49883844" } ] }, "receipt": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "api": "@hacker-news", "operation": "list_front_page", "billing": { "status": "settled", "reserved_credits": 1, "charged_credits": 1 } } } } ``` ## How it fits together 1. **Find a workflow.** Search the [catalog](https://docs.fous.com/guides/catalog) of public workflows, or [build your own](https://docs.fous.com/guides/building) in Studio from a website and a description. Every operation publishes an input schema, an output schema and verified examples. 2. **Call it.** `POST /v1/query` with `api`, `operation` and `input`. Pin a contract `version` when your integration depends on one. [Call a workflow](https://docs.fous.com/guides/typed-operations). 3. **Use the result.** Read `data.output`, keep `data.receipt.request_id`, and send an `Idempotency-Key` so a retry never pays twice. [Retries and idempotency](https://docs.fous.com/guides/replay). ## For AI agents Claude, Codex, Cursor, VS Code and any MCP client connect to the Fous MCP server and get five tools: search workflows, read their contracts, run them, run actions, and check a run. [Connect an AI agent](https://docs.fous.com/guides/mcp). Every page of these docs is also Markdown. Add `.md` to any URL, or start from [llms.txt](https://docs.fous.com/llms.txt). [Use with coding agents](https://docs.fous.com/guides/coding-agents). --- # Quickstart > Create an API key and make your first workflow call in five minutes. Source: https://docs.fous.com/quickstart ## 1. Create an API key Sign in to [Fous Studio](https://app.fous.com). Open **Developers** at the bottom of the sidebar, turn on **Developer mode**, then go to **Keys & connections** and create an API key. Keys belong to the organization you are in; its credits, limits and connected accounts apply to every call. Store the key as `FOUS_API_KEY` in your server environment. Never put it in browser code or a repository. ```bash export FOUS_API_KEY="fous_sk_..." ``` ## 2. Pick a workflow Every public workflow has a handle such as `@hacker-news` and one or more operations with a typed input. Search the catalog without a key: ```bash curl --get 'https://api.fous.com/v1/catalog' --data-urlencode 'query=hacker news' ``` The result lists each workflow's `api` handle and its `operations`. Open one in the catalog to read its input schema and verified examples: `GET /v1/catalog/detail?api=@hacker-news`. [Find a workflow](https://docs.fous.com/guides/catalog) explains the filters. ## 3. Call it Send the handle, the operation and an input that matches its schema. Add an `Idempotency-Key` so that a retried request returns the same result instead of running and charging again. **cURL** ```bash curl 'https://api.fous.com/v1/query' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Idempotency-Key: $FOUS_IDEMPOTENCY_KEY" \ -H 'Content-Type: application/json' \ -d '{"api":"@hacker-news","operation":"list_front_page","input":{"list_name":"show_hn","max_results":5}}' ``` **Node.js** ```javascript const response = await fetch('https://api.fous.com/v1/query', { method: 'POST', headers: { Authorization: `Bearer ${process.env.FOUS_API_KEY}`, 'Idempotency-Key': crypto.randomUUID(), 'Content-Type': 'application/json', }, body: JSON.stringify({ api: '@hacker-news', operation: 'list_front_page', input: { list_name: 'show_hn', max_results: 5 } }), }); const result = await response.json(); if (!response.ok) throw new Error(`${result.error.code}: ${result.error.message}`); console.log(result.data.output); ``` **Python** ```python import os import requests import uuid response = requests.post( "https://api.fous.com/v1/query", headers={ "Authorization": f"Bearer {os.environ['FOUS_API_KEY']}", "Idempotency-Key": str(uuid.uuid4()), }, json={ "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 } }, timeout=180, ) result = response.json() if not response.ok: raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}") print(result["data"]["output"]) ``` The Python example uses the `requests` package (`pip install requests`). Node.js 18 or later has `fetch` built in. ## 4. Read the result Check the HTTP status and `success`, then read `data.output`. The receipt tells you what ran and what it cost. ```json { "success": true, "data": { "output": { "stories": [ { "rank": 1, "title": "Show HN: Jeff – Jev-compatible 0.8B decision models, trained at home", "author": "firelex", "points": 230, "item_id": 49883844, "posted_at": "2026-09-28T20:23:36Z", "website_link": "https://github.com/firelex/jeff", "comment_count": 79, "discussion_link": "https://news.ycombinator.com/item?id=49883844" } ] }, "receipt": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "api": "@hacker-news", "operation": "list_front_page", "billing": { "status": "settled", "reserved_credits": 1, "charged_credits": 1 } } } } ``` A failure returns `success: false` and an `error` with a `code` to branch on. [Errors and limits](https://docs.fous.com/guides/errors) lists every code. ## 5. Keep the request ID The receipt's `request_id` (also sent as the `X-Request-Id` header) identifies the run. Look it up at any time without running the workflow again: ```bash curl "https://api.fous.com/v1/query/requests/$FOUS_REQUEST_ID" \ -H "Authorization: Bearer $FOUS_API_KEY" ``` After a timeout or a dropped connection, retry with the **same body and the same idempotency key**. Use a new key when you want fresh data. [Retries and idempotency](https://docs.fous.com/guides/replay). ## Next steps - [Call a workflow](https://docs.fous.com/guides/typed-operations): every request field, versions and private workflows. - [Connect an AI agent](https://docs.fous.com/guides/mcp): the same workflows as tools in Claude, Codex, Cursor and VS Code. - [API reference](https://docs.fous.com/api-reference): parameters and responses for every endpoint. --- # Authentication > Create an API key in Studio, send it as a bearer token, and know which endpoints need one. Source: https://docs.fous.com/authentication ## API keys Create a key in [Fous Studio](https://app.fous.com): open **Developers** at the bottom of the sidebar, turn on **Developer mode**, then go to **Keys & connections**. An organization Owner or Administrator can create and revoke keys. Keys start with `fous_sk_` and belong to one organization. A key has no scopes of its own: it can do everything its organization can, using that organization's credits, plan limits, private workflows and [connected accounts](https://docs.fous.com/guides/connected-accounts). It never reaches another organization's private workflows. Send the key as a bearer token on every authenticated request: ```http Authorization: Bearer fous_sk_... ``` Keep the key on a server or in an agent's environment. Executable examples in these docs read it from `FOUS_API_KEY`. ## Check a key `GET /v1/auth` returns `200` with an empty `data` object when the key is valid. It does not run anything and does not count against your execution quota. ```bash curl https://api.fous.com/v1/auth \ -H "Authorization: Bearer $FOUS_API_KEY" ``` ## Which endpoints need a key | Endpoint | Authentication | | -------------------------------------------------------------------- | ----------------------- | | `POST /v1/query`, request status, feedback | API key | | `GET /v1/auth`, `GET /v1/catalog/tools` | API key | | Catalog search, detail, suggestions, categories, sitemap, site icons | None | | Service discovery, health, OpenAPI document | None | | MCP server | API key or Fous sign-in | ## Authentication errors A missing, malformed, expired or revoked key returns `401` with one of `api_key_required`, `invalid_api_key`, `expired_api_key` or `revoked_api_key`, plus a `WWW-Authenticate: Bearer realm="Fous API"` header. If keys cannot be checked at that moment, the response is `503` with `api_key_verification_unavailable`; retry after the `Retry-After` header. ```json { "success": false, "error": { "type": "authentication_error", "status": 401, "code": "api_key_required", "message": "Provide Authorization: Bearer fous_sk_... header.", "retryable": false, "doc_url": "https://docs.fous.com/guides/errors#api_key_required", "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV" } } ``` ## Rotate or revoke a key Create a replacement in Studio, move your integration to it, then revoke the old key. A revoked key fails immediately with `revoked_api_key`. Never paste a key into a support message; share the `request_id` instead. ## MCP sign-in The MCP server accepts the same API key as a bearer header. Clients that support OAuth can instead sign in with a Fous account where sign-in is live: the server's `401` challenge carries the resource metadata the client needs, and you choose the organization during authorization. A Studio browser session is never an MCP credential. [Connect an AI agent](https://docs.fous.com/guides/mcp). Studio accounts, two-factor authentication and recovery are covered in [Accounts and sign-in](https://docs.fous.com/guides/accounts). --- # Call a workflow > The request and response contract of POST /v1/query: fields, versions, visibility, headers and cost. Source: https://docs.fous.com/guides/typed-operations Every workflow runs through one endpoint. Send the handle, the operation and an input that satisfies the operation's schema; Fous validates the input, runs the workflow and returns its typed output with a receipt. ```json { "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 } } ``` | Field | Required | Meaning | | ------------ | -------- | ---------------------------------------------------------------------------------------------------- | | `api` | Yes | The workflow handle, including the `@`. | | `operation` | Yes | The callable operation name from the catalog. Numeric IDs and display labels are not callable names. | | `input` | Yes | An object matching the operation's input schema. Dates and times go in the input, explicitly. | | `version` | No | A contract version to pin. Omit it to use the operation's default version. | | `stream` | No | `true` to receive progress as server-sent events. [Stream progress](https://docs.fous.com/guides/streaming). | | `response` | No | Field selection, output format or a target schema. [Shape the response](https://docs.fous.com/guides/responses). | | `visibility` | No | `public` or `private` when a handle exists on both sides. See below. | Unknown fields are rejected with `invalid_input`; the error's `details.issues` lists each failing path. Input that breaks the operation's schema returns `invalid_provider_input`. ## The response A completed call returns `200` with `success: true`, the output and the receipt. Headers tell you what the call cost before you parse the body. | Header | Meaning | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `X-Request-Id` | The request ID, also in `data.receipt.request_id`. Keep it for status lookup. | | `X-Fous-Cost-Credits` | Credits charged for this call. | | `X-Fous-Billing-Status` | `settled`, or `pending` while settlement finishes. | | `X-Fous-API` | The handle that ran. | | `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` | Your organization's requests per minute. | | `Idempotency-Replayed` | `true` when the body is the retained result of an earlier request with the same key. | `data.output` follows the operation's output schema. Workflows that return no match for an input fail with `404 not_found` rather than returning an empty object. ## Versions Each published contract is immutable and has an integer `version`. A workflow's default version does not move when a new one is published, so a call without `version` keeps working as it did. Pin `version` when a specific contract matters; a pinned version that is no longer available returns `409 workflow_version_unavailable`. ## Public and private workflows A handle can reach a public workflow and your organization's own private workflow with the same name. A private operation wins that collision. Set `visibility` to `public` or `private` to use one side only; `unknown_api_slug` means no workflow with that handle is available to your organization. ## Deadlines and cost A call has 170 seconds in total, and each workflow also enforces its own execution limit. A completed run costs **1 credit**. The credit is reserved before execution; a failure without a completed receipt releases it. Calls take one request and one running slot of your plan's quota; see [limits](https://docs.fous.com/guides/errors#rate-and-concurrency-limits). Send an `Idempotency-Key` whenever your client can retry: the same key and body return the same result instead of a second run and charge. [Retries and idempotency](https://docs.fous.com/guides/replay). ## Workflows that need an account or key Some operations read a signed-in website or a third-party service. They run with your organization's [connected account or access key](https://docs.fous.com/guides/connected-accounts). If the required access is not set up, the call returns `409 access_required` without a charge; `details.access` lists what to add, with an `add_url` into Studio. Operations that change something on a website (send, book, cancel) run the same way. The catalog and tool definitions mark them with `performs_actions`. --- # Find a workflow > Search public workflows, read an operation's contract, and page through results. Source: https://docs.fous.com/guides/catalog ## Search the catalog Catalog endpoints need no key. Each item has an `api` handle, a `name`, a `category`, the `sites` it reads and its `operations`. ```bash curl --get 'https://api.fous.com/v1/catalog' \ --data-urlencode 'query=weather' \ --data-urlencode 'limit=20' \ --data-urlencode 'sort=relevant' ``` | Parameter | Values | | ------------------ | ------------------------------------------------------------------ | | `query` | Free text, up to 100 characters. | | `api` | One handle, including the `@`. | | `category` | A category ID from `GET /v1/catalog/categories`. | | `sort` | `relevant` (default with a query), `popular`, `newest`, `updated`. | | `limit` | 1 to 100. Default 60. | | `max_cost_credits` | Only operations at or under this cost per call. | | `cursor` | The previous page's `next_cursor`. | Read `data.next_cursor` and pass it back as `cursor` with the same sort and filters. Stop when it is `null`. Private workflows never appear in the public catalog. For a search box, `GET /v1/catalog/suggest?query=hack` returns matching names and logos as the user types. ## Read the contract `GET /v1/catalog/detail?api=@hacker-news` returns one workflow with every operation's `input_schema`, `output_schema`, verified `examples`, `selectable_fields` for [response shaping](https://docs.fous.com/guides/responses), `contract_version`, `health` and `access`. ```bash curl --get 'https://api.fous.com/v1/catalog/detail' --data-urlencode 'api=@hacker-news' ``` Use the `operation` name and the schema exactly. Do not guess inputs from the name: required fields, enums and formats come from `input_schema`, and the verified example is a known-good input. `access` tells you what a workflow needs beyond a key: `open` runs as is, `own` needs your organization's [connected account or access key](https://docs.fous.com/guides/connected-accounts), and `mixed` workflows have operations of both kinds. ## Tool definitions for agents With an API key, `GET /v1/catalog/tools` lists every operation your organization can call, public and private, as a tool definition with `inputSchema`, `outputSchema`, MCP `annotations` and `performs_actions`. Filter with `api` or `query`, and page with the numeric `cursor`, 100 per page. This is the same list the [MCP server](https://docs.fous.com/guides/mcp) exposes. ## Pages, categories and icons - `GET /v1/catalog/sitemap` lists indexable workflow pages, 1,000 per `page`, with the terms each workflow is known for. - `GET /v1/catalog/categories` lists the 34 category IDs and labels. - `GET /v1/icons/{sha256}` serves a site icon by content hash. Catalog items link to these URLs in `logo_url` and `sites[].icon_url`. Every public workflow also has a page on [fous.com/workflows](https://fous.com/workflows) with a Markdown twin for agents. ## Build what is missing If no workflow fits, [build one](https://docs.fous.com/guides/building) in Studio from the website and a description of the task. It becomes callable through the same endpoint, privately for your organization. --- # Build a workflow > Describe a website task once in Studio. Run it with new inputs from code or an agent. Source: https://docs.fous.com/guides/building Workflows are built in [Fous Studio](https://app.fous.com). Each published operation has a reusable input and output contract that you can call from Studio, your code, or an AI agent. ## Describe the task Choose **Build**, add the website, and describe the steps or the data you need. Be specific about what changes between runs: a city, a search term, a date, a product. Those become the inputs. Fous explores the website, builds the operation and verifies it against real inputs. Follow the progress in Studio and review the result when the build is ready. ## Set access Your workflow is private to your organization. With **Share with the network** on, Fous may also publish a general version that other users can discover and run with their own accounts or keys. Builds submitted with sharing on are free, even when no general version is published. Sharing is on by default. An Owner or Administrator can turn it off in Organization settings, and any build can opt out. Turn sharing off before submitting confidential work. Changing the setting affects later submissions; already authorized contributions and existing public versions are not withdrawn. AI training data collection is a separate setting. See the [sharing terms](https://fous.com/terms#public-workflows) and the [Privacy Policy](https://fous.com/privacy#ai). If the website needs a sign-in, use a [connected account](https://docs.fous.com/guides/connected-accounts). Keep credentials in connection settings, never in a description or an input. ## Test and reuse Open the workflow's playground, review its inputs and run it with your own values. With Developer mode on, inspect the schema, the operation name and ready-made request examples. Then choose how to use it: - [Call the operation](https://docs.fous.com/guides/typed-operations) from any HTTP client. - [Connect an AI client](https://docs.fous.com/guides/mcp) and call it as a tool. Published contract versions are immutable. Pin `version` in direct calls when your integration depends on one. ## Build pricing Builds submitted with network sharing on are free. With sharing off, building or updating a workflow costs **100 credits**, charged when the build is ready ($1.00 at pay-as-you-go pricing). Failed, cancelled or reused builds release their reservation, except for credits that expired while reserved. Turning sharing on does not refund earlier builds. Runs are priced separately. [Billing and receipts](https://docs.fous.com/guides/billing). --- # Connected accounts > Run workflows on signed-in websites and third-party services without credentials in your requests. Source: https://docs.fous.com/guides/connected-accounts Connected accounts are in beta. Some websites may ask for reconnection or a verification step before they can be used. ## Connect a website In [Studio](https://app.fous.com), open **Connections**, or **Keys & connections** with Developer mode on. An Owner or Administrator adds the website and completes its sign-in steps. Fous verifies the session and saves the connection for your organization. Use **Reconnect** when the website needs a fresh sign-in. ## Access keys for services Some workflows call a service that needs your own API key rather than a browser session. Owners and Administrators store those under **Connections** in the **Access keys** section. When a workflow declares a required key for a site, calls run with your organization's saved key. A public workflow never exposes its creator's keys or sessions to other callers. ## What a call uses A call uses the connection or key authorized for your organization. The catalog marks what each workflow needs in `access` (`open`, `own` or `mixed`), and Studio shows a key badge on workflows that need your own account, an API key, or both. If the required access is missing, the call returns `409 access_required` and is not charged: ```json { "success": false, "error": { "type": "access_error", "status": 409, "code": "access_required", "message": "Connect your Spotify account to run this workflow.", "retryable": false, "doc_url": "https://docs.fous.com/guides/errors#access_required", "details": { "access": [ { "kind": "connection", "name": "Spotify", "site": "spotify.com", "status": "missing", "add_url": "https://app.fous.com/keys" } ] } } } ``` A connection that needs a fresh sign-in returns `auth_required`; a disconnected one returns `auth_revoked`. Fix it in Studio, then retry. Results from connected accounts are never cached. ## Actions and interrupted calls An action may have completed on the website even if its response was lost. Check the request's status and the destination before starting a new action. Reconnecting an account does not replay earlier actions. Use [idempotency keys](https://docs.fous.com/guides/replay) for HTTP retries, and `fous_get_run` for MCP status checks. ## Revoke access Revoke a connection or remove an access key in Studio to stop new calls from using it. You can also revoke access at the source website when it supports that. Revocation does not undo a completed action. --- # Connect an AI agent > Give Claude, Codex, Cursor, VS Code or any MCP client every Fous workflow as typed tools. Source: https://docs.fous.com/guides/mcp The Fous MCP server speaks Streamable HTTP at `https://api.fous.com/mcp`. It authenticates with the same API key as the HTTP API, sent as a bearer header, or with a Fous sign-in in clients that support OAuth where sign-in is live. ## Connect your client ### Claude Code Adds Fous for every project, reading the key from your shell environment. ```bash claude mcp add --scope user --transport http fous https://api.fous.com/mcp \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}" ``` Reference: https://code.claude.com/docs/en/mcp ### Codex Codex shares this configuration between its CLI and IDE extension. ```bash codex mcp add fous --url https://api.fous.com/mcp --bearer-token-env-var FOUS_API_KEY ``` Reference: https://developers.openai.com/codex/mcp/ ### Cursor For every project. Use .cursor/mcp.json in a repository to scope it to one project. File: `~/.cursor/mcp.json`. ```json { "mcpServers": { "fous": { "url": "https://api.fous.com/mcp", "headers": { "Authorization": "Bearer ${env:FOUS_API_KEY}" } } } } ``` Reference: https://cursor.com/docs/mcp ### VS Code VS Code asks for the key once and keeps it out of the file. File: `.vscode/mcp.json`. ```json { "inputs": [ { "type": "promptString", "id": "fous-api-key", "description": "Fous API key", "password": true } ], "servers": { "fous": { "type": "http", "url": "https://api.fous.com/mcp", "headers": { "Authorization": "Bearer ${input:fous-api-key}" } } } } ``` Reference: https://code.visualstudio.com/docs/copilot/customization/mcp-servers ### Claude Desktop Settings → Connectors → Add custom connector. Name it Fous, paste the URL and sign in with your Fous account. Custom connectors depend on your plan. ```bash https://api.fous.com/mcp ``` Reference: https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp ### Any MCP client Streamable HTTP with a Bearer header. The add-mcp helper writes most clients’ config. ```bash npx -y add-mcp https://api.fous.com/mcp -g -n fous \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}" ``` Reference: https://modelcontextprotocol.io/clients Each snippet reads `FOUS_API_KEY` from the environment, so nothing secret lands in a file or a repository. [Create a key](https://docs.fous.com/authentication) in Studio first. Studio also shows these snippets with your own key under **Keys & connections**. ## Make a first request Ask the agent for the data you need, in plain words: ```text Find five Show HN posts from today with their points and comment counts. ``` The agent calls `fous_search_workflows`, reads the matching operation's schema with `fous_get_workflow`, and runs it with `fous_run_workflow`. A workflow must exist in the public catalog or among your organization's private workflows; otherwise the agent tells you, and you can [build one](https://docs.fous.com/guides/building). ## The tools - `fous_search_workflows`: Search public workflows and your organization’s private ones. Free. - `fous_get_workflow`: List a workflow’s operations, or get one operation’s input and output schema. Free. - `fous_run_workflow`: Run one operation that reads data, with exact inputs. 1 credit. - `fous_run_action`: Run one operation that changes something on a website (sends, books, cancels), only when the user asked for it. 1 credit. - `fous_get_run`: Get a slow run’s result by its request_id, for up to 24 hours. Free. Searching, reading contracts and checking a run are free. Each completed run costs **1 credit**, the same as an HTTP call. ## Read-only and single-workflow servers Add `?read_only=true` to the URL for a model that calls tools unattended: tools that change something on a website are not offered. ```text https://api.fous.com/mcp?read_only=true ``` Expose one workflow by its name (the handle without the `@`). Each operation becomes its own tool with the operation's input schema, plus `fous_get_run`: ```text https://api.fous.com/mcp/workflows/hacker-news ``` The two can be combined. Access still follows the connected organization's permissions. ## Long runs and large results A tool call waits up to `wait_seconds` for the run: 50 seconds by default, from 1 to 170. When a run takes longer, the result has `status: "running"` and a `request_id`; the agent passes it to `fous_get_run` instead of calling the operation again. Results are retained for 24 hours. `max_chars` caps the returned JSON: 20,000 characters by default, from 1,000 to 150,000. Larger results are shortened and marked `truncated`; `include` and `exclude` select the fields that matter. ## Website actions `fous_run_workflow` only reads. Operations that change a website use `fous_run_action` and your organization's [connected account](https://docs.fous.com/guides/connected-accounts). Review the action and its details in your client before confirming. Cancelling after an action has reached the website may be too late to stop it; check the run by its request ID before trying again. ## Model APIs without a client Hosted model APIs can call the server directly. Use the read-only URL, since no person approves each call. **Anthropic Messages API** ```json { "mcp_servers": [ { "type": "url", "url": "https://api.fous.com/mcp?read_only=true", "name": "fous", "authorization_token": "" } ], "tools": [ { "type": "mcp_toolset", "mcp_server_name": "fous" } ] } ``` **OpenAI Responses API** ```json { "tools": [ { "type": "mcp", "server_label": "fous", "server_url": "https://api.fous.com/mcp?read_only=true", "authorization": "", "require_approval": "never" } ] } ``` The server also publishes an [OpenAPI document](https://docs.fous.com/openapi.json) and tool definitions at [`GET /v1/catalog/tools`](https://docs.fous.com/api-reference/listTools) for agents that call the HTTP API instead. --- # Use with coding agents > Point Claude Code, Codex or Cursor at these docs, and give them the Fous MCP server. Source: https://docs.fous.com/guides/coding-agents These docs are written for people and for the agents that write code with them. Every page is plain Markdown on request, and the whole site fits in one file. ## Markdown for every page | What | URL | | ------------------------- | ------------------------------------------------------------------------------------------- | | One page as Markdown | Add `.md` to its URL, for example `https://docs.fous.com/quickstart.md`. | | The same, by content type | Send `Accept: text/markdown` to any docs URL. | | A map of every page | [`https://docs.fous.com/llms.txt`](https://docs.fous.com/llms.txt) | | Every page in one file | [`https://docs.fous.com/llms-full.txt`](https://docs.fous.com/llms-full.txt) | | The API contract | [`https://api.fous.com/openapi.json`](https://docs.fous.com/openapi.json) | | Every public workflow | [`https://fous.com/llms.txt`](https://fous.com/llms.txt), with a Markdown page per workflow | The **Copy page** button at the top of each page copies that page's Markdown. Its menu also opens the page in Claude or ChatGPT, or copies a prompt that points a coding agent at it. ## Prompt a coding agent Paste this into Claude Code, Codex, Cursor or any agent with web access. Change the page URL to the guide you are following. ```text Read https://docs.fous.com/guides/coding-agents.md (the Fous docs page "Use with coding agents") and https://docs.fous.com/llms.txt. Then help me integrate Fous in this project, following those docs exactly. Ask me for anything the docs say I must decide, such as which workflow to call. Keep my Fous API key in an environment variable named FOUS_API_KEY. ``` For a whole integration, point the agent at `llms.txt` and let it fetch the pages it needs. An agent that has the [MCP server](https://docs.fous.com/guides/mcp) connected can also search and run workflows while it writes the code, which is the fastest way to confirm an input schema. ## Give the agent the MCP server Claude Code, Codex, Cursor and VS Code all take the server in one line or one file. The install snippets, with one-click install links where the client supports them, are in [Connect an AI agent](https://docs.fous.com/guides/mcp). ## What to tell the agent - Keep the key in `FOUS_API_KEY`, read it from the environment, and never commit it. - Send an `Idempotency-Key` with every `POST /v1/query` so retries never pay twice. [Retries and idempotency](https://docs.fous.com/guides/replay). - Read `success`, then `data.output`; on failure branch on `error.code`, and respect `error.retryable` and `Retry-After`. [Errors and limits](https://docs.fous.com/guides/errors). - Take inputs from the operation's `input_schema` in the catalog, never from its name. [Find a workflow](https://docs.fous.com/guides/catalog). --- # Stream progress > Follow a run with server-sent events and finish on the terminal result or error event. Source: https://docs.fous.com/guides/streaming Set `stream: true` on a call. The response is `text/event-stream`: progress events while the workflow runs, then exactly one `result` or `error` event that carries the same envelope a plain call returns. **cURL** ```bash curl --no-buffer 'https://api.fous.com/v1/query' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Idempotency-Key: $FOUS_IDEMPOTENCY_KEY" \ -H 'Content-Type: application/json' \ -d '{"api":"@hacker-news","operation":"list_front_page","input":{"list_name":"show_hn","max_results":5},"stream":true}' ``` **Node.js** ```javascript const response = await fetch('https://api.fous.com/v1/query', { method: 'POST', headers: { Authorization: `Bearer ${process.env.FOUS_API_KEY}`, 'Idempotency-Key': crypto.randomUUID(), 'Content-Type': 'application/json', }, body: JSON.stringify({ api: '@hacker-news', operation: 'list_front_page', input: { list_name: 'show_hn', max_results: 5 }, stream: true }), }); for await (const chunk of response.body.pipeThrough(new TextDecoderStream())) { process.stdout.write(chunk); // event: progress | result | error } ``` **Python** ```python import os import requests import uuid response = requests.post( "https://api.fous.com/v1/query", headers={ "Authorization": f"Bearer {os.environ['FOUS_API_KEY']}", "Idempotency-Key": str(uuid.uuid4()), }, json={ "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 }, "stream": True }, stream=True, timeout=180, ) for line in response.iter_lines(decode_unicode=True): if line: print(line) # event: progress | result | error ``` ## Event format Every event has a sequence `id`, an `event` name and one line of JSON `data`. A comment line `: keep-alive` arrives every 10 seconds during long work; ignore comment lines. ```text id: 1 event: progress data: {"request_id":"req_mg7x9f2kQ1nTz8bW3pLc0RhV","stage":"accepted","message":"Request received."} id: 3 event: progress data: {"request_id":"req_mg7x9f2kQ1nTz8bW3pLc0RhV","stage":"executing","message":"Getting your results…","api_reference":{"api":"@hacker-news","name":"Hacker News","logo_url":"https://api.fous.com/v1/icons/ed14…","category":"news"}} id: 5 event: result data: {"success":true,"data":{"output":{"stories":[]},"receipt":{"request_id":"req_mg7x9f2kQ1nTz8bW3pLc0RhV","api":"@hacker-news","operation":"list_front_page","billing":{"status":"settled","reserved_credits":1,"charged_credits":1}}}} ``` | Stage | Meaning | | ------------ | --------------------------------------------------------------- | | `accepted` | The request passed validation and admission. | | `preparing` | The workflow and its inputs are being prepared. | | `executing` | The workflow is running. `api_reference` names it from here on. | | `formatting` | The output is being shaped for delivery. | Do not require every stage or exactly one event per stage, and tolerate stages you do not know. Keep parsing across network chunk boundaries and finish only on `result` or `error`. ## Status codes A stream that has started uses HTTP `200`, even when it ends with an `error` event; read `error.status` from the event. Errors before the stream starts come back as plain JSON with their real status, for example `401` for a bad key, `400` for invalid fields or `429` when your quota is used up, so handle both shapes. A connection that closes without a terminal event is not a success. Keep the request ID from the first progress event and check [request status](https://docs.fous.com/api-reference/getRequest), or retry the same body with its original [idempotency key](https://docs.fous.com/guides/replay). A replayed request streams the terminal event immediately, without repeating progress. --- # Shape the response > Select fields, choose an output format, or project a result into your own JSON Schema. Source: https://docs.fous.com/guides/responses A call returns `data.output` as the operation's typed output. The `response` object changes that value without touching the envelope, the receipt or the price. | Option | Effect | | --------- | ----------------------------------------------------------------------------- | | `format` | `json` (default), `text` for a string, or `markdown` for a rendered document. | | `include` | Keep only these fields. | | `exclude` | Keep everything except these fields. | | `schema` | Project the output into this JSON Schema. | | `mapping` | Copy exact values into the schema with JSON Pointers. Needs `schema`. | Use `include` or `exclude` alone, or `schema` with an optional `mapping`. The two groups cannot be combined. ## Select fields Field paths come from the operation's `selectable_fields` in the [catalog](https://docs.fous.com/guides/catalog), such as `/stories/*/title`. The nested fields of a selected field come with it. ```json { "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 }, "response": { "include": ["/stories/*/title", "/stories/*/points"] } } ``` An unknown or duplicated path returns `invalid_response_include`; an `exclude` that leaves nothing returns `invalid_response_exclude`. ## Project into your schema With a `mapping`, Fous copies the exact source values into your structure. Nothing is invented and nothing is converted; an empty pointer addresses the whole output, and `*` projects arrays. ```json { "api": "@hacker-news", "operation": "list_front_page", "input": { "list_name": "show_hn", "max_results": 5 }, "response": { "schema": { "type": "object", "properties": { "posts": { "type": "array", "items": { "type": "object", "properties": { "headline": { "type": "string" }, "votes": { "type": "integer" } }, "required": ["headline", "votes"] } } }, "required": ["posts"], "additionalProperties": false }, "mapping": [ { "target": "/posts/*/headline", "source": "/stories/*/title" }, { "target": "/posts/*/votes", "source": "/stories/*/points" } ] } } ``` A `schema` without a `mapping` lets a model pick the source fields; the copied values are still the original ones. Prefer an explicit mapping when the output is known: it is deterministic and skips the model step. ## Limits `include`, `exclude` and `mapping` each take 1 to 1,000 unique entries. The serialized `schema` must stay within 8,000 bytes and cannot use external references. A valid schema can still fail once the output arrives if a required value is missing or incompatible: the call returns `422 response_schema_unfulfilled`, and a reservation that was not yet settled is released. A schema too large to map without a `mapping` returns `response_context_too_large`. --- # Retries and idempotency > Retry a call safely, recover a result after a dropped connection, and never pay twice. Source: https://docs.fous.com/guides/replay Send an `Idempotency-Key` header with `POST /v1/query` whenever your client can retry. One unique key per logical request; keep it with the request body. ```bash curl 'https://api.fous.com/v1/query' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Idempotency-Key: $FOUS_IDEMPOTENCY_KEY" \ -H 'Content-Type: application/json' \ -d '{"api":"@hacker-news","operation":"list_front_page","input":{"list_name":"show_hn","max_results":5}}' ``` A key is 1 to 255 printable ASCII characters without spaces, scoped to your organization. A UUID is a good key. Switching between JSON and streaming does not change the request's identity. ## What a retry returns | Situation | Response | | -------------------------------------- | ------------------------------------------------------------------------------------------- | | The original request completed | Its original status and body, with `Idempotency-Replayed: true`. No new run, no new charge. | | The original request is still running | `409 request_in_progress` with `Retry-After: 2` and the status URL in `Location`. | | The original stopped without finishing | `409 request_interrupted`. It will not run again under this key; check its status. | | The same key with a different body | `409 idempotency_key_conflict`. | | Too many keyed requests are unresolved | `429 unresolved_query_limit`. Check them before sending more. | Completed results are retained for 24 hours. A key is not a cache: after that window, or for an unrelated operation, send a new key. ## Check before you run again Keep `X-Request-Id` or `data.receipt.request_id` and look the request up: ```bash curl "https://api.fous.com/v1/query/requests/$FOUS_REQUEST_ID" \ -H "Authorization: Bearer $FOUS_API_KEY" ``` A status lookup never executes anything. For a keyed request it includes the retained `result`, its `response_status`, when it expires, and the current billing receipt. [Get a request](https://docs.fous.com/api-reference/getRequest). ## Fresh data on purpose A new key starts a new run with its own receipt and charge. Requests without a key are also new, billable runs each time. With a key, a run continues after your client disconnects, so the result is there when you retry. Without a key, disconnecting asks Fous to stop the run; that does not prove the work was not completed or charged, so check the receipt. --- # Accounts and sign-in > Sign in to Studio with email or Google, protect the account with two-factor authentication, and recover access. Source: https://docs.fous.com/guides/accounts ## Sign in Open [Fous Studio](https://app.fous.com) and continue with your email address or a Google account. - **Email**: enter your address to receive a 6-digit one-time code. Codes expire after 10 minutes. If the email does not arrive, check spam and wait for the resend cooldown before asking for another code. Disposable email domains cannot register. - **Google**: sign in with Google. If an account already exists for the same email address, the sign-in links to that profile. Inactive browser sessions expire on their own. Signing in again does not change saved workflows, keys or connections. ## Two-factor authentication Enable it under **Account → Security** (open the Account menu at the bottom of the sidebar and choose **Account**): 1. Select **Enable 2FA** to get a QR code and a setup key. 2. Scan the code or paste the key into an authenticator app such as Google Authenticator, 1Password or Authy. 3. Enter the 6-digit code to confirm. From then on, each sign-in asks for a current code after the email or Google step. Disable it on the same page by confirming with a current code. ## Change your email address Under **Account → Personal info**: confirm with a code sent to your current address, enter the new address, then confirm with the code sent there. ## Recover access - **Lost authenticator**: ask your organization's Owner or an Administrator to review your membership, or contact [support](mailto:hello@fous.com). - **Rate-limited codes**: wait for the cooldown shown on screen before requesting a new one. ## Delete your account Under **Account → Privacy & Data** you can delete your personal account. Deletion removes personal information and session tokens. If you are the sole Owner of an organization, that organization and its resources (keys, request logs, connections) are deleted with it. Transfer ownership first to keep it. [Organizations and permissions](https://docs.fous.com/guides/organizations). --- # Organizations and permissions > Workspaces, member roles, invitations, ownership transfer and organization settings. Source: https://docs.fous.com/guides/organizations Workflows, API keys, connected accounts and credits belong to an organization, not to a person. You can belong to several organizations and switch between them in Studio. ## Switch or create an organization Use the workspace menu at the top of the sidebar. It lists every organization you belong to with your role in each; select one to switch. **Create organization** (or the plus button) asks for a name and acceptance of the terms. The creator becomes the Owner and the organization receives its welcome credits. ## Roles | Capability | Owner | Administrator | Reader | | ------------------------------------------- | ------------------- | ------------- | ------ | | Run workflows in Studio and through the API | Yes | Yes | No | | Create and revoke API keys | Yes | Yes | No | | Manage billing, plans and credits | Yes | Yes | No | | Add and manage connected accounts | Yes | Yes | No | | Build and edit workflows | Yes | Yes | No | | Invite, remove and re-role members | Yes | Yes | No | | Update organization name, logo and settings | Yes | Yes | No | | Transfer ownership | Yes | No | No | | Leave the organization | No (transfer first) | Yes | Yes | | Delete the organization | Yes | No | No | Every organization has exactly one Owner. Readers see workflows, logs and activity without being able to run or change anything. ## Members Owners and Administrators manage the team under **Settings → Members**: - **Invite** by email with a role of Administrator or Reader. Invitations expire after 48 hours and can be cancelled before they are accepted. - **Change a role** between Administrator and Reader. - **Transfer ownership** by choosing **Owner (transfers ownership)** for a member. It takes effect immediately and makes the previous Owner an Administrator. - **Remove a member**. They lose access to workflows, keys and billing at once. The Owner cannot be removed. - **Leave**: Administrators and Readers can leave from the Members list. An Owner transfers ownership first, or deletes the organization. ## Settings Under **Settings**, Owners and Administrators can: - Update the organization's name and logo. - Turn **Share with the network** on or off for new builds. [Build a workflow](https://docs.fous.com/guides/building). - Choose whether execution data may be used for AI training. When off, the organization's requests are excluded from training data. - Delete the organization (Owner only). Deletion stops running executions and purges stored action results, responses and connection attempts. --- # Billing and receipts > What a call costs, how to read a receipt, and how request status and retention work. Source: https://docs.fous.com/guides/billing | Activity | Price | | ------------------------------------ | --------------- | | Completed workflow run | **1 credit** | | Searching, reading contracts, status | **Free** | | Build with network sharing on | **Free** | | Build or update with sharing off | **100 credits** | At pay-as-you-go pricing 100 credits cost $1.00 USD; plan pricing differs. Manage credits, auto-recharge and spending limits in [Studio](https://app.fous.com) under **Billing**. Each call has its own receipt, and the `X-Fous-Cost-Credits` header repeats the charge. ## Read the receipt | Field | Meaning | | -------------------------- | ------------------------------------------------------------ | | `request_id` | The identifier for status lookup and support. | | `billing.status` | `not_started`, `pending`, `settled` or `released`. | | `billing.reserved_credits` | Credits reserved before the run. | | `billing.charged_credits` | The confirmed charge, or `null` while settlement is pending. | Fous reserves the full price before execution. A failed run without a completed receipt releases the reservation, as does a response-shaping failure before delivery. Once a completed receipt exists, a later delivery problem can still leave the charge in place; the status endpoint shows the final state. `insufficient_balance` (`402`) means the organization has no credits for the call; `monthly_spend_limit_exceeded` means the call would pass the organization's monthly limit. Both are set under **Billing** in Studio. ## Check status and retention ```bash curl "https://api.fous.com/v1/query/requests/$FOUS_REQUEST_ID" \ -H "Authorization: Bearer $FOUS_API_KEY" ``` The lookup returns the request's `status`, its receipt and whether it can be rated. For a request sent with an idempotency key it also returns the retained `result`, its `response_status` and `result_expires_at`. Lookups never run or charge anything and do not count against the execution quota. [Get a request](https://docs.fous.com/api-reference/getRequest). Completed results of keyed requests are retained for 24 hours. Action outcomes and responses kept to resolve interrupted requests may be retained for up to 90 days. Deleting an organization purges its action results, responses and connection attempts. A `404` means no record exists in your organization; it does not prove an earlier request was not billed. ## Rate a result Successful calls to public workflows can be rated for 30 days: send `{"value": 1}` or `{"value": -1}` to `POST /v1/query/requests/{request_id}/feedback`, or `{"value": null}` to remove a rating. Status shows `can_rate` and, when rating is not available, `feedback_unavailable_reason`: your own organization's workflows and private workflows are not eligible. [Rate a request](https://docs.fous.com/api-reference/feedback). ## Customer agreements Organizations with a negotiated agreement manage it in Studio under **Billing**: - **Terms and pricing**: the agreed name, price, cadence (monthly or one-time), credits per payment and terms. - **Credits**: each batch expires after the agreed number of calendar months; agreement credits are listed next to subscription and top-up credits. Agreements are independent of plans such as Pro and of top-up pricing. - **Payments**: activate the agreement, choose automatic card billing or manual monthly payment where allowed, pay a due period, update the default card, and download invoices and receipts. - **Cancellation**: give notice according to the agreement's notice period. It takes effect at the end of the notice window across full billing months, and payments due before that date remain payable. --- # Errors and limits > The error envelope, what to do per status, rate and concurrency limits, and every error code. Source: https://docs.fous.com/guides/errors Every failure returns `success: false` and an `error` object. Branch on `error.code`; `error.retryable` says whether sending the same request again can succeed, and `error.doc_url` links to the code's entry on this page. ```json { "success": false, "error": { "type": "validation_error", "status": 422, "code": "invalid_provider_input", "message": "input.max_results must be at most 100.", "param": "input.max_results", "retryable": false, "doc_url": "https://docs.fous.com/guides/errors#invalid_provider_input", "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV" } } ``` Validation errors name the field in `param` and list every issue in `details.issues`. Errors that happen after a run started also carry the `receipt`. [Error schema](https://docs.fous.com/api-reference/schemas#error). ## What to do per status | Status | Typical cause | Action | | ------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------ | | `400` | Malformed JSON, unknown fields, a bad idempotency key | Fix the request from `details.issues`. | | `401` | Missing, invalid, expired or revoked key | [Authentication](https://docs.fous.com/authentication). | | `402` | No credits, or a spending limit reached | Add credits or raise the limit under Billing in Studio. | | `404` | Unknown request ID, or the workflow found nothing for the input | Check the ID or the input. | | `409` | Idempotency conflicts, version gone, access or sign-in needed | Read the code; keep the original key; fix access in Studio. | | `413` | Body over 4 MB | Send less. | | `422` | Input or `response` options break the operation's contract | Read the operation's schema in the catalog. | | `429` | Rate or concurrency limit | Wait for `Retry-After`, then retry. | | `502`, `503`, `504` | The website, the engine or a dependency did not answer in time | Keep the request ID and check status before repeating a paid call. | Stopping a run in Studio returns `409 request_cancelled`. Stopped runs are not charged; if a write action had already reached the website, `details.reached_website` is `true`. ## Rate and concurrency limits | Scope | Limit | | ------------------------------------------------------ | ----------------------------------------------------------------------------- | | Workflow calls, per organization | Your plan's requests per minute and concurrent runs, shown in `X-RateLimit-*` | | Status, key checks, tool definitions, per organization | 3,000 requests per minute | | Feedback, per organization | 30 requests per minute | | Public catalog, per client | 600 requests per minute; suggestions 90 per minute | | Request body | 4 MB | | Deadlines | 170 seconds for a call; 30 seconds for every other endpoint | Each call counts against the organization's requests per minute and holds one running slot. `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (epoch seconds) report the quota; exceeding it returns `429 organization_rate_limit`. A call waits up to 10 seconds for a free slot, then returns `429 organization_concurrency_limit` with `Retry-After: 2`. Quotas follow your plan or agreement; review them in Studio under **Billing**. Status lookups and `GET /v1/auth` use the separate metadata limit and never consume execution quota, so polling a slow run is safe at a reasonable interval. ## Streaming A stream that has started reports a later failure as a terminal `error` event while the HTTP status stays `200`; read `error.status` from the event. [Stream progress](https://docs.fous.com/guides/streaming). Never include a key in a support message. Share the `request_id`, the `code` and a redacted request. ## Error codes Every code the API returns, with its HTTP status and whether the same request can succeed later. Website errors (`502`) describe the source site; `credentials_*`, `auth_*` and `access_required` point to Studio. | Code | Status | Retry | Meaning | | --- | --- | --- | --- | | `invalid_json` | 400 | no | The body is not valid JSON. | | `invalid_input` | 400 | no | The body breaks the endpoint’s schema; details.issues lists each path. | | `body_too_large` | 413 | no | The body is over 4 MB. | | `invalid_idempotency_key` | 400 | no | Use 1 to 255 printable ASCII characters without spaces. | | `request_timeout` | 408 | yes | An endpoint other than POST /v1/query took over 30 seconds. | | `endpoint_not_found` | 404 | no | No endpoint has this method and path. | | `not_found` | 404 | no | No such request or resource, or the workflow found no result. | | `api_key_required` | 401 | no | Send Authorization: Bearer . | | `invalid_api_key` | 401 | no | The key is malformed or unknown. | | `expired_api_key` | 401 | no | The key passed its expiration. | | `revoked_api_key` | 401 | no | The key was deleted. | | `api_key_verification_unavailable` | 503 | yes | Keys cannot be checked right now. | | `rate_limit_exceeded` | 429 | yes | Too many status, tool, feedback or catalog requests. | | `unknown_api_slug` | 422 | no | No workflow with this handle is available to your organization. | | `unknown_operation` | 422 | no | The operation does not belong to this workflow or is unavailable. | | `api_retired` | 410 | no | The operation was removed or replaced. | | `workflow_version_unavailable` | 409 | no | The pinned version is no longer available. | | `invalid_provider_input` | 422 | no | input does not match the operation’s input schema. | | `unsupported_input` | 422 | no | The workflow cannot handle this input value. | | `ambiguous_result` | 409 | no | More than one result matched; send a more specific input. | | `invalid_response_include` | 422 | no | A response.include field is unknown, duplicated or ambiguous. | | `invalid_response_exclude` | 422 | no | A response.exclude field is unknown or leaves no field. | | `response_schema_unfulfilled` | 422 | no | The result cannot fill response.schema. | | `response_context_too_large` | 422 | no | response.schema is too large to map without mapping. | | `insufficient_balance` | 402 | no | Not enough credits. Add credits in Studio → Billing. | | `spend_limit_exceeded` | 402 | no | The call would pass your spend limit. | | `monthly_spend_limit_exceeded` | 402 | no | The call would pass your monthly spend limit. | | `organization_rate_limit` | 429 | yes | Your organization used its requests per minute. | | `organization_concurrency_limit` | 429 | yes | Too many requests are running at once. | | `unresolved_query_limit` | 429 | no | Too many keyed requests are unresolved; check them first. | | `admission_unavailable` | 503 | yes | Requests cannot be admitted right now. | | `idempotency_key_conflict` | 409 | no | The key was already used with a different body. | | `request_in_progress` | 409 | yes | The original request is still running; retry with the same key. | | `request_interrupted` | 409 | no | The original request stopped and will not run again under this key. | | `auth_required` | 409 | no | A connected account must sign in again (Studio → Connections). | | `auth_revoked` | 409 | no | A connected account was disconnected (Studio → Connections). | | `credentials_missing` | 422 | no | A key or variable the workflow needs is missing. | | `credentials_rejected` | 422 | no | The website rejected a key or variable. | | `source_permission_denied` | 422 | no | The website denied the account access. | | `action_unconfirmed` | 422 | no | An action’s outcome could not be confirmed; check the website. | | `workflow_partially_completed` | 422 | no | An earlier step may have completed; check the website. | | `workflow_execution_failed` | 502 | yes | The website could not be reached. | | `upstream_not_found` | 502 | no | The website returned 404 or 410. | | `upstream_http_error` | 502 | yes | The website returned an error instead of the data. | | `source_rate_limited` | 502 | yes | The website is rate-limiting requests. | | `source_blocked` | 502 | yes | The website is not allowing the request right now. | | `execution_timeout` | 504 | yes | The workflow did not finish within its time limit. | | `engine_unavailable` | 503 | yes | Workflows cannot run right now. | | `response_formatting_unavailable` | 503 | yes | Model-assisted response.schema mapping is unavailable. | | `billing_unavailable` | 503 | yes | Credits cannot be reserved right now. | | `catalog_unavailable` | 503 | yes | The catalog is temporarily unavailable. | | `response_delivery_failed` | 500 | no | The workflow finished but its result was not delivered. | | `internal_error` | 500 | yes | An unexpected error. | --- # API reference > Endpoints, request bodies and response schemas of the Fous API, version 1.2.0. Source: https://docs.fous.com/api-reference The Fous API is served at `https://api.fous.com`. Every response is JSON with a `success` flag: a result in `data`, or an `error` with a `code` to branch on. The contract is published as [OpenAPI 3.1](https://docs.fous.com/openapi.json), version **1.2.0**. ## Authentication Send your organization’s key as `Authorization: Bearer $FOUS_API_KEY`. Catalog and service endpoints are public. [Create a key](https://docs.fous.com/authentication). ## Endpoints ### Workflows Call a workflow with api, operation and input. - `POST /v1/query` [Call a workflow](https://docs.fous.com/api-reference/query) ### Requests Status, results and feedback of earlier requests. - `GET /v1/query/requests/{request_id}` [Get a request](https://docs.fous.com/api-reference/getRequest) - `POST /v1/query/requests/{request_id}/feedback` [Rate a request](https://docs.fous.com/api-reference/feedback) ### Catalog Find workflows, their operations and their contracts. - `GET /v1/catalog/categories` [List categories](https://docs.fous.com/api-reference/listApiCategories) - `GET /v1/catalog` [Search workflows](https://docs.fous.com/api-reference/listApis) - `GET /v1/catalog/detail` [Get a workflow](https://docs.fous.com/api-reference/getApi) - `GET /v1/catalog/suggest` [Suggest workflows](https://docs.fous.com/api-reference/suggestApis) - `GET /v1/catalog/sitemap` [List workflow pages](https://docs.fous.com/api-reference/listApiPages) - `GET /v1/icons/{sha256}` [Get a site icon](https://docs.fous.com/api-reference/getIcon) - `GET /v1/catalog/tools` [List tool definitions](https://docs.fous.com/api-reference/listTools) ### Service Discovery, health and this document. - `GET /` [Service discovery](https://docs.fous.com/api-reference/getService) - `GET /health` [Service health](https://docs.fous.com/api-reference/getHealth) - `GET /v1/auth` [Check an API key](https://docs.fous.com/api-reference/authenticate) - `GET /openapi.json` [OpenAPI document](https://docs.fous.com/api-reference/getOpenApi) - `GET /.well-known/api-catalog` [API catalog](https://docs.fous.com/api-reference/getApiCatalog) ## Schemas [QueryRequest, Receipt, QueryResult, Error, RequestStatus, CatalogApi, Site, Tool](https://docs.fous.com/api-reference/schemas): the shared request and response objects. ## Errors Every failure is an [Error](https://docs.fous.com/api-reference/schemas#error). The [errors guide](https://docs.fous.com/guides/errors) lists each `error.code`, its HTTP status and whether a retry can succeed. --- # Schemas > The shared request and response objects of the Fous API. Source: https://docs.fous.com/api-reference/schemas ## QueryRequest Provide api, operation and input to call a workflow. Use include or exclude alone, or schema with optional mapping. - `api` (string, required): The workflow handle, including the @, for example @hacker-news. - `operation` (string, required): The callable operation name from the catalog, for example list_front_page. - `version` (integer): Pin an immutable method contract version. Omit to keep the method’s established default version; publishing a new version never moves that default. - `input` (JSON value, required): An object that satisfies the operation’s input schema. - `stream` (boolean): When true, the response is a server-sent event stream of progress, then one result or error event. - `response` (object): Shapes data.output without changing the envelope. - `format` (string): json keeps the typed output; text returns a string; markdown renders a Markdown document. Default "json". One of "json", "text", "markdown". - `include` (array of string): Only these output fields, as paths from the operation’s selectable fields. - `exclude` (array of string): Every declared output field except these (and their nested fields). - `schema` (object): A JSON Schema (at most 8 KB) the output is projected into. - `mapping` (array of object): JSON Pointer pairs that copy source values into the target schema. Requires schema. - `target` (string, required): JSON Pointer into the response schema, for example /temperature. - `source` (string, required): JSON Pointer into the workflow output, for example /current/temp_c. - `visibility` (string): A handle reaches your organization’s private API and the public API alike; a private method wins a name collision. Set public or private to use one side only. One of "public", "private". ```json { "type": "object", "properties": { "api": { "type": "string", "pattern": "^@[a-z0-9][a-z0-9_-]{0,99}$" }, "operation": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,99}$" }, "version": { "type": "integer", "exclusiveMinimum": 0, "maximum": 2147483647, "description": "Pin an immutable method contract version. Omit to keep the method’s established default version; publishing a new version never moves that default." }, "input": { "$ref": "#/components/schemas/QueryRequest/$defs/__schema0" }, "stream": { "type": "boolean" }, "response": { "type": "object", "properties": { "format": { "default": "json", "type": "string", "enum": [ "json", "text", "markdown" ] }, "include": { "minItems": 1, "maxItems": 1000, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 }, "uniqueItems": true }, "exclude": { "minItems": 1, "maxItems": 1000, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 1000 }, "uniqueItems": true, "description": "Every declared output field except these (and their nested fields)." }, "schema": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, "mapping": { "minItems": 1, "maxItems": 1000, "type": "array", "items": { "type": "object", "properties": { "target": { "type": "string", "maxLength": 1000 }, "source": { "type": "string", "maxLength": 1000 } }, "required": [ "target", "source" ], "additionalProperties": false } } }, "additionalProperties": false, "allOf": [ { "not": { "anyOf": [ { "required": [ "include", "exclude" ] }, { "required": [ "include", "schema" ] }, { "required": [ "include", "mapping" ] }, { "required": [ "exclude", "schema" ] }, { "required": [ "exclude", "mapping" ] } ] } }, { "if": { "required": [ "mapping" ] }, "then": { "required": [ "schema" ] } } ] }, "visibility": { "type": "string", "enum": [ "public", "private" ], "description": "A handle reaches your organization’s private API and the public API alike; a private method wins a name collision. Set public or private to use one side only." } }, "additionalProperties": false, "$defs": { "__schema0": { "anyOf": [ { "anyOf": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" }, { "type": "null" } ] }, { "type": "array", "items": { "$ref": "#/components/schemas/QueryRequest/$defs/__schema0" } }, { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/components/schemas/QueryRequest/$defs/__schema0" } } ] } }, "description": "Provide api, operation and input to call a workflow. Use include or exclude alone, or schema with optional mapping.", "required": [ "api", "operation", "input" ], "dependentRequired": { "visibility": [ "api" ] } } ``` ## Receipt - `request_id` (string, required): Identifies the request for status lookup and support. - `api` (string or null, required): The workflow that ran, or null before one was resolved. - `operation` (string or null, required): The operation that ran, or null before one was resolved. - `billing` (object, required): What the request reserved and charged. - `status` (string, required): not_started, pending, settled or released. One of "not_started", "pending", "settled", "released". - `reserved_credits` (number, required): Credits reserved before execution. - `charged_credits` (number or null, required): The confirmed charge, or null while settlement is pending. ```json { "type": "object", "properties": { "request_id": { "type": "string" }, "api": { "type": [ "string", "null" ] }, "operation": { "type": [ "string", "null" ] }, "billing": { "type": "object", "properties": { "status": { "enum": [ "not_started", "pending", "settled", "released" ] }, "reserved_credits": { "type": "number" }, "charged_credits": { "type": [ "number", "null" ] } }, "required": [ "status", "reserved_credits", "charged_credits" ], "additionalProperties": false } }, "required": [ "request_id", "api", "operation", "billing" ], "additionalProperties": false } ``` ## QueryResult - `success` (true, required): Always true on a completed result. - `data` (object, required): The output and its receipt. - `output` (JSON value, required): The workflow’s output. - `receipt` (Receipt, required): The execution receipt. ```json { "type": "object", "properties": { "success": { "const": true }, "data": { "type": "object", "required": [ "output", "receipt" ], "properties": { "output": { "description": "The workflow’s output." }, "receipt": { "$ref": "#/components/schemas/Receipt" } }, "additionalProperties": true } }, "required": [ "success", "data" ], "additionalProperties": false } ``` ## Error - `success` (false, required): Always false on an error. - `error` (object, required): The failure. - `type` (string, required): The error family, for example validation_error or rate_limit_error. - `code` (string, required): The specific code to branch on. Every code is listed in the errors guide. - `message` (string, required): A readable explanation, safe to show in logs. - `status` (integer, required): The HTTP status, repeated so streamed errors carry it too. - `retryable` (boolean): Whether sending the same request again later can succeed. Wait Retry-After first when present; after a 5xx, check a keyed request’s status before retrying. - `request_id` (string): The request this error belongs to. - `param` (string): The request field that failed validation, as a dotted path. - `doc_url` (string): This code’s entry in the errors guide. - `details` (JSON value): Extra structured context, for example details.issues for validation errors. - `receipt` (Receipt): The receipt, when the request reached execution. ```json { "type": "object", "properties": { "success": { "const": false }, "error": { "type": "object", "required": [ "type", "code", "message", "status" ], "properties": { "type": { "type": "string" }, "code": { "type": "string" }, "message": { "type": "string" }, "status": { "type": "integer" }, "retryable": { "type": "boolean", "description": "Whether sending the same request again later can succeed. Wait Retry-After first when present; after a 5xx, check a keyed request’s status before retrying." }, "request_id": { "type": "string" }, "param": { "type": "string" }, "doc_url": { "type": "string", "description": "This code’s entry in the errors guide." }, "details": {}, "receipt": { "$ref": "#/components/schemas/Receipt" } }, "additionalProperties": true } }, "required": [ "success", "error" ], "additionalProperties": false } ``` ## RequestStatus - `success` (true, required) - `data` (object, required) - `request_id` (string, required): The request that was looked up. - `status` (string, required): reserving, processing, succeeded, rejected, refund_pending, failed or interrupted. - `result` (QueryResult or Error or null): The retained terminal envelope for requests sent with an Idempotency-Key, or null. - `response_status` (number or null): The HTTP status of the retained result. - `result_expires_at` (string or null): When the retained result is deleted. - `error_code` (string or null): The error code of a failed request. - `receipt` (Receipt): The current billing receipt. - `feedback` (number or null): Your rating of this request: 1, -1 or null. One of 1, -1, null. - `can_rate` (boolean): Whether a rating can be sent now. - `feedback_unavailable_reason` (string or null): own_api, private_api, request_incomplete, expired or not_independent. ```json { "type": "object", "properties": { "success": { "const": true }, "data": { "type": "object", "required": [ "request_id", "status" ], "properties": { "request_id": { "type": "string" }, "status": { "type": "string" }, "result": { "oneOf": [ { "$ref": "#/components/schemas/QueryResult" }, { "$ref": "#/components/schemas/Error" }, { "type": "null" } ] }, "response_status": { "type": [ "number", "null" ] }, "result_expires_at": { "type": [ "string", "null" ] }, "error_code": { "type": [ "string", "null" ] }, "receipt": { "$ref": "#/components/schemas/Receipt" }, "feedback": { "enum": [ 1, -1, null ] }, "can_rate": { "type": "boolean" }, "feedback_unavailable_reason": { "type": [ "string", "null" ] } }, "additionalProperties": true } }, "required": [ "success", "data" ], "additionalProperties": false } ``` ## CatalogApi - `api` (string, required): The handle, including the @. - `name` (string, required): The workflow’s readable name. - `description` (string): What the workflow returns. - `category` (string): One category ID from the categories endpoint. One of "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other". - `website_url` (string or null): The website the workflow reads. - `logo_url` (string or null): An icon URL served by this API. - `availability` (string): available or coming_soon. - `visibility` ("public") - `is_enabled` (true) - `sites` (array of Site): The sites the workflow reads, the product's own first. - `operations` (array of object, required): The operations you can call. - `id` (integer): The numeric operation ID used by tools and catalog cursors. Not a callable name. - `operation` (string): The callable operation name. - `label` (string): The readable label. - `contract_version` (integer): The default contract version. - `cost_credits` (number): Credits charged per completed run. - `sites` (array of Site): The sites this method reads. ```json { "type": "object", "required": [ "api", "name", "operations" ], "properties": { "api": { "type": "string", "pattern": "^@[a-z0-9][a-z0-9_-]{0,99}$", "example": "@x_com" }, "name": { "type": "string" }, "description": { "type": "string" }, "category": { "type": "string", "enum": [ "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other" ] }, "website_url": { "type": [ "string", "null" ] }, "logo_url": { "type": [ "string", "null" ] }, "availability": { "type": "string" }, "visibility": { "const": "public" }, "is_enabled": { "const": true }, "sites": { "description": "The sites the workflow reads, the product's own first.", "type": "array", "items": { "$ref": "#/components/schemas/Site" } }, "operations": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "operation": { "type": "string" }, "label": { "type": "string" }, "contract_version": { "type": "integer" }, "cost_credits": { "type": "number" }, "sites": { "description": "The sites this method reads.", "type": "array", "items": { "$ref": "#/components/schemas/Site" } } }, "additionalProperties": true } } }, "additionalProperties": true } ``` ## Site - `name` (string, required): The site’s readable name. - `host` (string, required): The hostname the workflow reads. - `icon_url` (string or null, required): An icon URL served by this API, or null. ```json { "type": "object", "required": [ "name", "host", "icon_url" ], "properties": { "name": { "type": "string" }, "host": { "type": "string" }, "icon_url": { "type": [ "string", "null" ] } }, "additionalProperties": false } ``` ## Tool - `name` (string, required): Stable across renames: fous_{operation_id}. - `title` (string, required): The readable label, for example "List front page". - `description` (string, required): Starts with the workflow and its website; ends with the cost. - `inputSchema` (object, required): JSON Schema of the operation’s input. - `outputSchema` (object or null, required): JSON Schema of the operation’s output, or null. - `annotations` (object): MCP tool annotations (readOnlyHint, destructiveHint, openWorldHint). - `operation_id` (integer, required): The numeric operation ID. - `api` (string, required): The workflow handle, including the @. - `visibility` (string): public, or private for your organization’s own workflows. One of "public", "private". - `operation` (string, required): The callable operation name. - `contract_version` (integer, required): The contract version the tool definition describes. - `workflow` (string): The workflow’s readable name. - `site` (string or null): The hostname the operation reads, or null. - `performs_actions` (boolean): Running it changes something on the website (sends, books, cancels). ```json { "type": "object", "required": [ "name", "title", "description", "inputSchema", "outputSchema", "operation_id", "api", "operation", "contract_version" ], "properties": { "name": { "type": "string", "description": "Stable across renames: fous_{operation_id}." }, "title": { "type": "string", "description": "The readable label, for example \"List front page\"." }, "description": { "type": "string", "description": "Starts with the workflow and its website; ends with the cost." }, "inputSchema": { "type": "object" }, "outputSchema": { "type": [ "object", "null" ] }, "annotations": { "type": "object", "description": "MCP tool annotations (readOnlyHint, destructiveHint, openWorldHint).", "additionalProperties": true }, "operation_id": { "type": "integer" }, "api": { "type": "string", "pattern": "^@[a-z0-9][a-z0-9_-]{0,99}$", "example": "@x_com" }, "visibility": { "enum": [ "public", "private" ] }, "operation": { "type": "string" }, "contract_version": { "type": "integer" }, "workflow": { "type": "string" }, "site": { "type": [ "string", "null" ] }, "performs_actions": { "type": "boolean", "description": "Running it changes something on the website (sends, books, cancels)." } }, "additionalProperties": true } ``` --- # Call a workflow > Run one workflow operation with exact inputs and get its typed output and a receipt. Source: https://docs.fous.com/api-reference/query `POST /v1/query` A call with api, operation and input costs 1 credit and takes one request and one running slot of your plan. The full price is reserved before execution; failures without a completed receipt release it. 170-second overall request deadline; individual workflows also enforce their execution limits. With Idempotency-Key, work continues after client disconnection; completed terminal results are retained for 24 hours. Identical retries return the same status/body. Concurrent retries return 409 with Retry-After and Location. A changed request under the same key returns 409. Stale unfinished claims never dispatch again. Without a key, a repeated POST is a new billable request. Switching JSON/SSE transport does not change identity. Authentication: `Authorization: Bearer $FOUS_API_KEY`. ## Headers - `Idempotency-Key` (string): Unique opaque key per logical query, scoped to the authenticated organization. Retain it for retries. ## Request body Required. JSON. - `api` (string, required): The workflow handle, including the @, for example @hacker-news. - `operation` (string, required): The callable operation name from the catalog, for example list_front_page. - `version` (integer): Pin an immutable method contract version. Omit to keep the method’s established default version; publishing a new version never moves that default. - `input` (JSON value, required): An object that satisfies the operation’s input schema. - `stream` (boolean): When true, the response is a server-sent event stream of progress, then one result or error event. - `response` (object): Shapes data.output without changing the envelope. - `format` (string): json keeps the typed output; text returns a string; markdown renders a Markdown document. Default "json". One of "json", "text", "markdown". - `include` (array of string): Only these output fields, as paths from the operation’s selectable fields. - `exclude` (array of string): Every declared output field except these (and their nested fields). - `schema` (object): A JSON Schema (at most 8 KB) the output is projected into. - `mapping` (array of object): JSON Pointer pairs that copy source values into the target schema. Requires schema. - `target` (string, required): JSON Pointer into the response schema, for example /temperature. - `source` (string, required): JSON Pointer into the workflow output, for example /current/temp_c. - `visibility` (string): A handle reaches your organization’s private API and the public API alike; a private method wins a name collision. Set public or private to use one side only. One of "public", "private". ## Response 200 Completed JSON result, or an SSE stream ending with result/error. SSE HTTP status stays 200; terminal errors carry error.status. The progress stages are accepted, preparing, executing and formatting; executing and formatting carry api_reference, the workflow called. Clients should tolerate additional stages. - `X-Request-Id`: - `Idempotency-Replayed`: - `Location`: - `X-Fous-Billing-Status`: - `X-RateLimit-Limit`: Your plan’s requests per minute. - `X-RateLimit-Remaining`: Requests left in the current minute. - `X-RateLimit-Reset`: Unix time, in seconds, when the oldest request leaves the window. - `success` (true, required): Always true on a completed result. - `data` (object, required): The output and its receipt. - `output` (JSON value, required): The workflow’s output. - `receipt` (Receipt, required): The execution receipt. ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/query' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Idempotency-Key: $FOUS_IDEMPOTENCY_KEY" \ -H 'Content-Type: application/json' \ -d '{"api":"@hacker-news","operation":"list_front_page","input":{"list_name":"show_hn","max_results":5}}' ``` ## Example response ```json { "success": true, "data": { "output": { "stories": [ { "rank": 1, "title": "Show HN: Jeff – Jev-compatible 0.8B decision models, trained at home", "author": "firelex", "points": 230, "item_id": 49883844, "posted_at": "2026-09-28T20:23:36Z", "age": "4 hours ago", "website_link": "https://github.com/firelex/jeff", "website_domain": "github.com", "comment_count": 79, "discussion_link": "https://news.ycombinator.com/item?id=49883844" }, { "rank": 2, "title": "Show HN: Pirating the Pirates", "author": "piotrgrabowski", "points": 396, "item_id": 49880036, "posted_at": "2026-09-28T15:54:15Z", "age": "8 hours ago", "website_link": "https://mubi.com/en/notebook/posts/pirating-the-pirates", "website_domain": "mubi.com", "comment_count": 206, "discussion_link": "https://news.ycombinator.com/item?id=49880036" } ] }, "receipt": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "api": "@hacker-news", "operation": "list_front_page", "billing": { "status": "settled", "reserved_credits": 1, "charged_credits": 1 } } } } ``` --- # Get a request > Look up a request by ID: its status, billing receipt and, for keyed requests, the retained result. Source: https://docs.fous.com/api-reference/getRequest `GET /v1/query/requests/{request_id}` Authentication: `Authorization: Bearer $FOUS_API_KEY`. ## Path parameters - `request_id` (string, required) ## Response 200 Success - `success` (true, required) - `data` (object, required) - `request_id` (string, required): The request that was looked up. - `status` (string, required): reserving, processing, succeeded, rejected, refund_pending, failed or interrupted. - `result` (QueryResult or Error or null): The retained terminal envelope for requests sent with an Idempotency-Key, or null. - `response_status` (number or null): The HTTP status of the retained result. - `result_expires_at` (string or null): When the retained result is deleted. - `error_code` (string or null): The error code of a failed request. - `receipt` (Receipt): The current billing receipt. - `feedback` (number or null): Your rating of this request: 1, -1 or null. One of 1, -1, null. - `can_rate` (boolean): Whether a rating can be sent now. - `feedback_unavailable_reason` (string or null): own_api, private_api, request_incomplete, expired or not_independent. ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/query/requests/req_mg7x9f2kQ1nTz8bW3pLc0RhV' \ -H "Authorization: Bearer $FOUS_API_KEY" ``` ## Example response ```json { "success": true, "data": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "status": "succeeded", "result": { "success": true, "data": { "output": { "stories": [ { "rank": 1, "title": "Show HN: Jeff – Jev-compatible 0.8B decision models, trained at home", "author": "firelex", "points": 230, "item_id": 49883844, "posted_at": "2026-09-28T20:23:36Z", "age": "4 hours ago", "website_link": "https://github.com/firelex/jeff", "website_domain": "github.com", "comment_count": 79, "discussion_link": "https://news.ycombinator.com/item?id=49883844" }, { "rank": 2, "title": "Show HN: Pirating the Pirates", "author": "piotrgrabowski", "points": 396, "item_id": 49880036, "posted_at": "2026-09-28T15:54:15Z", "age": "8 hours ago", "website_link": "https://mubi.com/en/notebook/posts/pirating-the-pirates", "website_domain": "mubi.com", "comment_count": 206, "discussion_link": "https://news.ycombinator.com/item?id=49880036" } ] }, "receipt": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "api": "@hacker-news", "operation": "list_front_page", "billing": { "status": "settled", "reserved_credits": 1, "charged_credits": 1 } } } }, "response_status": 200, "result_expires_at": "2026-10-07T08:41:12.000Z", "error_code": null, "receipt": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "api": "@hacker-news", "operation": "list_front_page", "billing": { "status": "settled", "reserved_credits": 1, "charged_credits": 1 } }, "feedback": null, "can_rate": true, "feedback_unavailable_reason": null } } ``` --- # Rate a request > Rate a successful call to a public workflow, or remove your rating. Source: https://docs.fous.com/api-reference/feedback `POST /v1/query/requests/{request_id}/feedback` Authentication: `Authorization: Bearer $FOUS_API_KEY`. ## Path parameters - `request_id` (string, required) ## Request body Required. JSON. - `value` (number or null, required): One of 1, -1, null. ## Response 200 Success - `success` (true, required) - `data` (object, required) - `request_id` (string) - `value` (number or null, required): One of 1, -1, null. ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/query/requests/req_mg7x9f2kQ1nTz8bW3pLc0RhV/feedback' \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"value":1}' ``` ## Example response ```json { "success": true, "data": { "request_id": "req_mg7x9f2kQ1nTz8bW3pLc0RhV", "value": 1 } } ``` --- # List categories > The category IDs and labels used by the catalog. Source: https://docs.fous.com/api-reference/listApiCategories `GET /v1/catalog/categories` The supported Discover category IDs and labels. Each API shares one category across its methods. Authentication: none. This endpoint is public. ## Response 200 Success - `success` (true, required) - `data` (object, required) - `items` (array of object, required) - `id` (string, required): One of "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other". - `label` (string, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog/categories' ``` ## Example response ```json { "success": true, "data": { "items": [ { "id": "ai", "label": "AI" }, { "id": "blockchain", "label": "Blockchain" }, { "id": "commerce", "label": "Commerce" }, { "id": "news", "label": "News" } ] } } ``` --- # Search workflows > Search the public catalog by text, handle, category or cost. Source: https://docs.fous.com/api-reference/listApis `GET /v1/catalog` Lists active public APIs only. API handles include the @ prefix; each method supplies its callable operation and human-readable label. Authentication: none. This endpoint is public. ## Query parameters - `query` (string) - `cursor` (string) - `category` (string): One of "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other". - `api` (string) - `limit` (integer): Default 60. - `sort` (string): One of "relevant", "popular", "newest", "updated". - `max_cost_credits` (number): Maximum estimated cost per call in credits. ## Response 200 Success - `success` (true, required) - `data` (object, required) - `items` (array of CatalogApi, required) - `next_cursor` (string or null, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog?query=hacker+news&limit=20' ``` ## Example response ```json { "success": true, "data": { "items": [ { "api": "@hacker-news", "name": "Hacker News", "description": "Hacker News provides current ranked story lists, searchable stories and comments, discussion threads, and monthly hiring posts.", "category": "news", "website_url": "https://news.ycombinator.com", "logo_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7", "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ], "availability": "available", "visibility": "public", "access": "open", "is_enabled": true, "operations": [ { "id": 1684, "contract_version": 1, "operation": "list_front_page", "label": "list_front_page", "cost_credits": 1, "health": { "status": "healthy", "verified_at": "2026-09-30T01:30:41.451Z" }, "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ], "access": [] }, { "id": 1698, "contract_version": 1, "operation": "get_discussion", "label": "get_discussion", "cost_credits": 1, "health": { "status": "healthy", "verified_at": "2026-10-05T13:19:49.017Z" }, "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ], "access": [] } ] } ], "next_cursor": null } } ``` --- # Get a workflow > One public workflow with every operation’s schemas, verified examples and selectable fields. Source: https://docs.fous.com/api-reference/getApi `GET /v1/catalog/detail` One public workflow: its operations with input and output schemas, verified examples, selectable fields and the sites it reads. Private workflows are never returned here. Authentication: none. This endpoint is public. ## Query parameters - `api` (string, required) - `operation_cursor` (string) - `operation_id` (integer) ## Response 200 Success - `success` (true, required) - `data` (object, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog/detail?api=@hacker-news' ``` ## Example response ```json { "success": true, "data": { "api": "@hacker-news", "name": "Hacker News", "description": "Hacker News provides current ranked story lists, searchable stories and comments, discussion threads, and monthly hiring posts.", "category": "news", "website_url": "https://news.ycombinator.com", "logo_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7", "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ], "availability": "available", "visibility": "public", "access": "open", "is_enabled": true, "operations": [ { "id": 1684, "contract_version": 1, "versions": [ { "id": 1684, "contract_version": 1, "is_latest": true } ], "operation": "list_front_page", "label": "list_front_page", "description": "Current stories of one Hacker News list, in ranked order.", "input_schema": { "type": "object", "properties": { "list_name": { "type": "string", "enum": [ "top", "newest", "best", "ask_hn", "show_hn", "jobs" ], "default": "top", "description": "Hacker News list to read, for example ask_hn." }, "max_results": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30, "description": "Maximum number of stories to return." } } }, "output_schema": { "type": "object", "required": [ "stories" ], "properties": { "stories": { "type": "array", "items": { "type": "object", "properties": { "rank": { "type": "integer" }, "title": { "type": "string" }, "author": { "type": "string" }, "points": { "type": "integer" }, "item_id": { "type": "integer" }, "posted_at": { "type": "string", "format": "date-time" }, "website_link": { "type": [ "string", "null" ] }, "comment_count": { "type": "integer" }, "discussion_link": { "type": "string" } } } } } }, "examples": [ { "input": { "list_name": "show_hn", "max_results": 5 }, "output": { "stories": [ { "rank": 1, "title": "Show HN: Jeff – Jev-compatible 0.8B decision models, trained at home", "author": "firelex", "points": 230, "item_id": 49883844, "posted_at": "2026-09-28T20:23:36Z", "age": "4 hours ago", "website_link": "https://github.com/firelex/jeff", "website_domain": "github.com", "comment_count": 79, "discussion_link": "https://news.ycombinator.com/item?id=49883844" }, { "rank": 2, "title": "Show HN: Pirating the Pirates", "author": "piotrgrabowski", "points": 396, "item_id": 49880036, "posted_at": "2026-09-28T15:54:15Z", "age": "8 hours ago", "website_link": "https://mubi.com/en/notebook/posts/pirating-the-pirates", "website_domain": "mubi.com", "comment_count": 206, "discussion_link": "https://news.ycombinator.com/item?id=49880036" } ] } } ], "selectable_fields": [ "/stories", "/stories/*/title", "/stories/*/points" ], "cost_credits": 1, "is_enabled": true, "is_available": true, "health": { "status": "healthy", "verified_at": "2026-09-30T01:30:41.451Z" }, "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ], "access": [] } ], "operations_count": 4, "next_operation_cursor": "MTY5OA", "related": [] } } ``` --- # Suggest workflows > Names and logos that match a partial query, for a search box. Source: https://docs.fous.com/api-reference/suggestApis `GET /v1/catalog/suggest` Authentication: none. This endpoint is public. ## Query parameters - `query` (string, required) - `category` (string): One of "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other". ## Response 200 Success - `success` (true, required) - `data` (object, required) - `items` (array of object, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog/suggest?query=hacker' ``` ## Example response ```json { "success": true, "data": { "items": [ { "api": "@hacker-news", "name": "Hacker News", "logo_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ] } } ``` --- # List workflow pages > Indexable public workflow pages with their search terms, 1,000 per page. Source: https://docs.fous.com/api-reference/listApiPages `GET /v1/catalog/sitemap` Authentication: none. This endpoint is public. ## Query parameters - `page` (integer): Default 0. - `category` (string): One of "ai", "blockchain", "commerce", "communication", "data", "developer-tools", "documents", "education", "energy", "entertainment", "finance", "food", "government", "health", "identity", "jobs", "legal", "logistics", "maps", "marketing", "media", "news", "payments", "productivity", "real-estate", "science", "search", "security", "social", "sports", "storage", "travel", "weather", "other". ## Response 200 Success - `success` (true, required) - `data` (object, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog/sitemap?page=0' ``` ## Example response ```json { "success": true, "data": { "items": [ { "api": "@hacker-news", "name": "Hacker News", "terms": [ "news stories", "discussion comments", "hiring posts" ], "summary": "Ranked stories, search results, discussions and hiring posts from Hacker News.", "category": "news", "updated_at": "2026-09-29T04:23:16.260604+00:00", "logo_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7", "sites": [ { "name": "Hacker News", "host": "news.ycombinator.com", "icon_url": "https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7" } ] } ], "pages": 1, "total": 496, "categories": [ { "id": "news", "label": "News", "count": 12, "updated_at": "2026-09-29T04:23:16Z" } ] } } ``` --- # Get a site icon > A site icon by its content hash. Immutable and cacheable. Source: https://docs.fous.com/api-reference/getIcon `GET /v1/icons/{sha256}` A stored site icon, immutable and cacheable, addressed by its content hash. Authentication: none. This endpoint is public. ## Path parameters - `sha256` (string, required) ## Response 200 The icon image. ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/icons/ed1403710142a4bb7392e3ca5e3878016d071acf9daf7aa8a12e82f28dbb7fa7' ``` --- # List tool definitions > Every operation your organization can call, as tool definitions for agents. Source: https://docs.fous.com/api-reference/listTools `GET /v1/catalog/tools` Every workflow operation your organization can call (public plus your private workflows) as a tool definition with inputSchema and outputSchema, 100 per page. name stays stable; title is the readable label; performs_actions (and annotations.destructiveHint) marks operations that change something on the website. Filter with api or query to load one workflow’s tools. Authentication: `Authorization: Bearer $FOUS_API_KEY`. ## Query parameters - `cursor` (string) - `operation_id` (integer) - `api` (string): One workflow’s operations, by handle (the @ is optional). - `query` (string): Words that must all appear in the handle, name or description. ## Response 200 Success - `success` (true, required) - `data` (object, required) - `items` (array of Tool, required) - `next_cursor` (string or null, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/catalog/tools?api=@hacker-news' \ -H "Authorization: Bearer $FOUS_API_KEY" ``` ## Example response ```json { "success": true, "data": { "items": [ { "name": "fous_1684", "title": "List front page", "description": "Hacker News (news.ycombinator.com): current stories of one list, in ranked order. 1 credit per run.", "inputSchema": { "type": "object", "properties": { "list_name": { "type": "string", "enum": [ "top", "newest", "best", "ask_hn", "show_hn", "jobs" ], "default": "top", "description": "Hacker News list to read, for example ask_hn." }, "max_results": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30, "description": "Maximum number of stories to return." } } }, "outputSchema": { "type": "object", "required": [ "stories" ], "properties": { "stories": { "type": "array", "items": { "type": "object", "properties": { "rank": { "type": "integer" }, "title": { "type": "string" }, "author": { "type": "string" }, "points": { "type": "integer" }, "item_id": { "type": "integer" }, "posted_at": { "type": "string", "format": "date-time" }, "website_link": { "type": [ "string", "null" ] }, "comment_count": { "type": "integer" }, "discussion_link": { "type": "string" } } } } } }, "annotations": { "readOnlyHint": true, "destructiveHint": false, "openWorldHint": true }, "operation_id": 1684, "api": "@hacker-news", "visibility": "public", "operation": "list_front_page", "contract_version": 1, "workflow": "Hacker News", "site": "news.ycombinator.com", "performs_actions": false, "access": [] } ], "next_cursor": null } } ``` --- # Service discovery > Service status and links to the docs, the OpenAPI document and the MCP server. Source: https://docs.fous.com/api-reference/getService `GET /` Authentication: none. This endpoint is public. ## Response 200 Success - `success` (true, required) - `data` (object, required) - `service` (string) - `version` (string) - `product` (string) - `status` (string) - `build_available` (boolean) - `registered_providers` (integer) - `endpoint` ("/v1/query") - `links` (object): Where agents find the docs, this document and the MCP server. - `docs` (string) - `openapi` (string) - `mcp` (string) - `mcp_guide` (string) - `llms_txt` (string) - `status` (string) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/' ``` ## Example response ```json { "success": true, "data": { "service": "Fous External API", "version": "v1", "product": "Fous API Builder", "status": "ready", "build_available": true, "registered_providers": 496, "endpoint": "/v1/query", "links": { "docs": "https://docs.fous.com", "openapi": "https://api.fous.com/openapi.json", "mcp": "https://api.fous.com/mcp", "mcp_guide": "https://docs.fous.com/guides/mcp", "llms_txt": "https://fous.com/llms.txt", "status": "https://api.fous.com/health" } } } ``` --- # Service health > Operational readiness of the API and its dependencies. Source: https://docs.fous.com/api-reference/getHealth `GET /health` Operational readiness. A degraded response uses the health envelope, not an execution error. Authentication: none. This endpoint is public. ## Response 200 Healthy - `status` (string, required): One of "ok", "degraded". - `service` (string, required) - `timestamp` (string, required) - `uptime_seconds` (integer, required) - `checks` (object, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 503 ## Example request ```bash curl 'https://api.fous.com/health' ``` ## Example response ```json { "status": "ok", "service": "api-external", "timestamp": "2026-10-06T08:40:12.798Z", "uptime_seconds": 223, "checks": { "service": { "ok": true } } } ``` --- # Check an API key > Verify that a key is valid without running anything. Source: https://docs.fous.com/api-reference/authenticate `GET /v1/auth` Authentication: `Authorization: Bearer $FOUS_API_KEY`. ## Response 200 Success - `success` (true, required) - `data` (object, required) ## Errors Every error uses the Error schema: branch on `error.code`. Codes are listed at https://docs.fous.com/guides/errors. - 400 - 401 (headers: WWW-Authenticate) - 402 - 403 - 404 - 408 - 409 - 410 - 413 - 422 - 429 (headers: Retry-After) - 500 - 502 - 503 (headers: Retry-After) - 504 ## Example request ```bash curl 'https://api.fous.com/v1/auth' \ -H "Authorization: Bearer $FOUS_API_KEY" ``` ## Example response ```json { "success": true, "data": {} } ``` --- # OpenAPI document > The OpenAPI 3.1 document this reference is generated from. Source: https://docs.fous.com/api-reference/getOpenApi `GET /openapi.json` Authentication: none. This endpoint is public. ## Response 200 Success ## Example request ```bash curl 'https://api.fous.com/openapi.json' ``` --- # API catalog > An RFC 9727 linkset of the APIs this host serves. Source: https://docs.fous.com/api-reference/getApiCatalog `GET /.well-known/api-catalog` A linkset of the APIs this host serves: this document, the docs, the MCP server and status. Authentication: none. This endpoint is public. ## Response 200 RFC 9264 linkset. - `linkset` (array of object, required) ## Example request ```bash curl 'https://api.fous.com/.well-known/api-catalog' \ -H 'Accept: application/linkset+json' ``` ## Example response ```json { "linkset": [ { "anchor": "https://api.fous.com/v1/query", "service-desc": [ { "href": "https://api.fous.com/openapi.json", "type": "application/vnd.oai.openapi+json;version=3.1" } ], "service-doc": [ { "href": "https://docs.fous.com", "type": "text/html" } ], "status": [ { "href": "https://api.fous.com/health", "type": "application/json" } ] }, { "anchor": "https://api.fous.com/mcp", "service-doc": [ { "href": "https://docs.fous.com/guides/mcp", "type": "text/html" } ], "status": [ { "href": "https://api.fous.com/health", "type": "application/json" } ] } ] } ``` ---