# Build and manage from code

> Build tools, connect accounts and save keys over the API or from an AI agent, with the same key that runs tools.

Source: https://docs.fous.com/guides/manage-from-code

Build tools, connect website accounts and save service keys through the same API that Studio uses, with the key you already use to run tools. In Studio, website accounts are under **Connections** and service keys are under **Developers → Variables**. An agent with the [MCP server](https://docs.fous.com/guides/mcp) can use these capabilities as tools.

## What a key may do

| Credential                                             | Reads | Runs | Builds and deletes tools | Connects accounts | Saves keys |
| ------------------------------------------------------ | ----- | ---- | ------------------------ | ----------------- | ---------- |
| Your organization's API key (`fous_sk_…`)              | yes   | yes  | yes                      | yes               | yes        |
| An agent key an owner or admin connected (`fous_ag_…`) | yes   | yes  | yes                      | yes               | yes        |
| An MCP sign-in with a Fous account (OAuth)             | yes   | yes  | no                       | no                | no         |

A credential that lacks the scope gets `403 insufficient_scope`, and the `WWW-Authenticate` header names the scope: `tools:read`, `tools:run`, `tools:write`, `connections:write` or `variables:write`. An agent key deletes a tool as the person who connected it, who must still be an owner or admin; your organization's own key deletes as the organization.

## Build a tool

Describe the data or action you need and name the website. Fous explores the site, builds the tool, verifies it with real runs and publishes it to your organization as a private tool.

```bash
curl -X POST https://api.fous.com/v1/builds \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Idempotency-Key: build-kayak-fares-1" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Flight prices between two airports on a date from kayak.com", "urls": ["https://www.kayak.com"]}'
```

The answer is `202` with the build. A build takes a few minutes; read it with `wait` and one call at a time follows it to the end:

```bash
curl "https://api.fous.com/v1/builds/$BUILD_ID?wait=170" \
  -H "Authorization: Bearer $FOUS_API_KEY"
```

`status` goes from `queued` through `exploring`, `compiling`, `verifying` and `publishing` to `ready`, `failed` or `cancelled`. A ready build names its tool in `api` and its operation in `method`, and `prepared_request` holds an input the builder verified it with, ready for [`POST /v1/query`](https://docs.fous.com/guides/typed-operations). A failed build says why in `error`; fix what it names (a clearer prompt, another page, a connected account) and `POST /v1/builds/{build_id}/retry`.

A build that waits for a person says so in `waiting_for`. With `connections`, an account needs a fresh sign-in. With `approval`, the build wants to do something with a connected account other than read, and `pending_approval` describes the request; show it to the person and record their decision with `POST /v1/builds/{build_id}/approvals/{approval_id}` (`decision`: `approve` or `decline`, `scope`: `once` or `build`). Never decide for them. [Approving a build's actions](https://docs.fous.com/guides/connected-accounts#approving-a-builds-actions).

Retain the submission's `Idempotency-Key`: the same key and body return the same build; a different body with that key returns `409 submission_conflict`. Retry failed or cancelled builds through their `/retry` endpoint, optionally providing updated `connections` or `environment` values. `POST /v1/builds/{build_id}/cancel` stops an unwanted build.

Build list and detail responses include `active_time` when recorded. `elapsed_ms` counts completed active work, including earlier attempts, rather than time since submission. During an active stage, add the current interval from `started_at`, capped at `valid_until`; queued, paused and connection-waiting time does not count. Refresh the response before extending the timer beyond that bound. An admission response may omit `active_time`.

Send `api` to edit a tool your organization built instead of building a new one, or `api` with `method_id` to customize a public tool as your own. `connections` binds [connected accounts](https://docs.fous.com/guides/connected-accounts) by alias, and `environment` passes keys the tool needs as an `.env`, saved with the tool and never returned. `contribute` chooses network sharing for this build; when omitted, the organization's setting applies. The [pricing](https://docs.fous.com/guides/building#build-pricing) is the same as in Studio: free with sharing on within the plan's monthly allowance, otherwise 100 credits, charged when ready.

## Your own tools

`GET /v1/tools` lists the tools your organization built, with their methods; `GET /v1/tools/{api}` reads one, with `refund_credits` (what deleting it gives back). Public tools and search stay under [`/v1/catalog`](https://docs.fous.com/guides/catalog).

Delete one you built with `DELETE /v1/tools/{api}`, or one method of it with `DELETE /v1/tools/{api}/methods/{method_id}`; the tool stays until its last method goes. A public tool cannot be deleted. A tool with a build in progress answers `409 api_change_conflict`: wait for the build or cancel it first.

Tools unused for 90 days are archived. `idle_expires_at`, `archived_at` and `restorable_until` describe their lifecycle; `POST /v1/tools/{api}/restore` restores a tool within 30 days of archiving. See [unused tools](https://docs.fous.com/guides/building#unused-tools).

## Connect an account

A connection signs a website account in on Fous's own server, exactly as the Connections page does, one step at a time. Your code relays each form to the person; their credentials pass through to the website and are never stored. `consent` must be `true`: the person agreed that Fous signs in for them.

```bash
curl -X POST https://api.fous.com/v1/connections/attempts \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"website_url": "shopify.com", "consent": true}'
```

Then read the attempt with `wait` until it needs something:

```bash
curl "https://api.fous.com/v1/connections/attempts/$ATTEMPT_ID?wait=60" \
  -H "Authorization: Bearer $FOUS_API_KEY"
```

| `status`    | What it means                                                                                                                                       |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `working`   | The website is loading. Read again with `wait`.                                                                                                     |
| `challenge` | The website asks for something. `form` lists its `fields` (`email`, `password`, `text` or `code`) or `alternatives` to choose from, with `step_id`. |
| `verified`  | The sign-in worked. `POST …/confirm` saves the connection.                                                                                          |
| `ready`     | The account is connected; `connection_id` names it. Tools and builds that need it use it from now on.                                               |
| `failed`    | `notice` says why. With `can_retry`, `POST …/retry` tries another sign-in method.                                                                   |

Answer a challenge with what the person typed:

```bash
curl -X POST "https://api.fous.com/v1/connections/attempts/$ATTEMPT_ID/submit?wait=60" \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"challenge_id": "…", "step_id": "…", "fields": {"email": "me@example.com", "password": "…"}}'
```

A choice between alternatives goes in `choice` instead of `fields`. The attempt lasts 30 minutes; `POST …/cancel` ends it early.

`GET /v1/connections` lists the organization's connections. One with `status: "reconnect"` needs a fresh sign-in: start an attempt with its `connection_id`. `PATCH /v1/connections/{id}` renames one and `DELETE` revokes it, after which tools that needed it answer `409 auth_revoked`.

## Save a key for a service

Some tools call a service with your own API key. Save it once for the site and every tool that calls the site uses it:

```bash
curl -X PUT https://api.fous.com/v1/variables \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"site": "myshop.com", "name": "ACCESS_TOKEN", "value": "shpat_…"}'
```

`name` is the variable as the tool reads it; the default `API_KEY` becomes the site's own, such as `MYSHOP_API_KEY`. `GET /v1/variables` lists saved keys with a `hint` of each value, never the value itself. `PATCH /v1/variables/{id}` changes a label or value and `DELETE` removes one.

## Also on the same door

`PUT /v1/catalog/version-preference` pins the method version this credential runs for a tool (`operation_id`, `replace`), `GET /v1/tools/{api}/environment` shows what a tool of yours runs with (its saved variables, masked, and its connections), and `GET /v1/usage?period=30d` reports spend through the API by day and by tool. Runs started with `Idempotency-Key` and `X-Fous-Stoppable: 1` can be stopped with `POST /v1/query/cancel`.

## From an AI agent

The same lives on the MCP server as `fous_build_tool`, `fous_get_build`, `fous_delete_tool`, `fous_connect_account`, `fous_connections` and `fous_variables`, with `fous_status` for where the agent stands. `fous_build_tool` takes an `idempotency_key` so a repeated call returns the same build, and `fous_get_build` with `retry: true` resumes a failed or cancelled one. The server offers each one only to a credential with its scope, and none of them on a [read-only](https://docs.fous.com/guides/mcp#read-only-and-single-tool-servers) connection. `fous_connect_account` carries the whole sign-in: the agent shows you each form, you type into your own client, and the agent sends your answers on; it is told never to type credentials on its own or keep them.

Agents that connected themselves with your email (`fous_ag_…`) have these scopes. You see what each agent did under **API keys** in Studio and can revoke it there.
