# Migrate from the old API

> Every change from the old tool API, with each old call next to its new one, and a prompt that moves your code for you.

Source: https://docs.fous.com/guides/migration
Index: https://docs.fous.com/llms.txt

Your API keys, the base URL and the MCP server stay the same. Tools are now methods: each operation of a tool is one method, named by its site's domain and the operation, such as `companiesmarketcap.com/get_company_size`. Private tools stay private to your organization.

`POST /v1/query`, `GET /v1/query/requests/{request_id}` and `POST /v1/query/cancel` keep working [until 10 November 2026](#until-the-sunset). Every other old endpoint has stopped.

## Run a method

```diff
- POST /v1/query
- Idempotency-Key: 6a1f0c2e
+ POST /v1/runs
  {
-   "api": "@companiesmarketcap",
-   "operation": "get_company_size",
+   "method": "companiesmarketcap.com/get_company_size",
    "input": { "company": "Coca-Cola" }
  }
```

```diff
  {
-   "success": true,
-   "data": {
-     "output": { "ticker": "KO", "market_cap_usd": 404720000000 },
-     "receipt": {
-       "request_id": "req_run_01m69eaghdfsdrysprnyfwr8xy",
-       "billing": { "charged_credits": 1 }
-     }
-   }
+   "id": "run_01m69eaghdfsdrysprnyfwr8xy",
+   "status": "completed",
+   "data": { "ticker": "KO", "market_cap_usd": 404720000000 },
+   "cost": { "credits": 1 },
+   "duration_ms": 1693
  }
```

- `"version": 2` is now `"method": "companiesmarketcap.com/get_company_size@2"`.
- `visibility`, `stream`, `response` and the `Idempotency-Key` header are gone. Your own method is found before a public one with the same slug; take the fields you need from `data`.
- To find a slug, `GET /v1/search?platform=companiesmarketcap.com` lists the site's methods, and every old-format answer names its method in `data.receipt.method`.

## Slow runs

The old call waited up to 170 seconds. `POST /v1/runs` waits `wait` seconds (0 to 60, 30 by default), then answers `202` with `"status": "running"` and the run's `id`:

```diff
- GET  /v1/query/requests/req_run_01m69eaghdfsdrysprnyfwr8xy
+ GET  /v1/runs/run_01m69eaghdfsdrysprnyfwr8xy?wait=30
- POST /v1/query/cancel  {"idempotency_key": "6a1f0c2e"}
+ POST /v1/runs/run_01m69eaghdfsdrysprnyfwr8xy/cancel
```

## Errors

```diff
  {
-   "success": false,
    "error": {
-     "type": "authentication_error",
-     "code": "revoked_api_key",
-     "status": 401,
-     "retryable": false,
+     "code": "unauthorized",
+     "reason": "revoked_api_key",
      "message": "API key has been revoked.",
+     "next_step": "Send Authorization: Bearer <key>. Create a key in Fous Studio: …"
    }
  }
```

Branch on the HTTP status and `error.code`. The codes that changed:

```text
invalid_api_key, expired_api_key, revoked_api_key  → unauthorized (401)
insufficient_balance                               → insufficient_credits (402)
spend_limit_exceeded, monthly_spend_limit_exceeded → insufficient_credits (402)
rate_limit_exceeded, organization_rate_limit,
  organization_concurrency_limit                   → rate_limited (429)
unknown_api_slug, unknown_operation                → not_found (404)
auth_required, credentials_missing                 → connection_required
source_blocked                                     → upstream_blocked (503)
source_rate_limited, upstream_http_error           → upstream_error (503)
execution_timeout                                  → upstream_timeout (503)
internal_error                                     → server_error (500)
invalid_input (400)                                → invalid_input (422)
```

Where the old code was more specific, `error.reason` keeps it, such as `revoked_api_key`, `spend_limit` or `site_rate_limited`.

Every code is in [Errors and limits](https://docs.fous.com/guides/errors.md).

## Find methods

```diff
- GET /v1/catalog?query=coca-cola+market+cap
+ GET /v1/search?query=coca-cola+market+cap
- GET /v1/catalog/suggest?query=coca
+ GET /v1/search?query=coca&suggest=true
- GET /v1/catalog/detail?api=@companiesmarketcap
+ GET /v1/search?platform=companiesmarketcap.com
+ GET /v1/methods/companiesmarketcap.com/get_company_size
```

The old `data.items`, each a tool with its `operations`, is now `results`, one method each, with its `slug`, `effect` and `input_schema`. `/v1/catalog/categories`, `/v1/catalog/sitemap` and `/v1/catalog/tools` are gone.

## Your methods

```diff
- GET    /v1/tools
+ GET    /v1/methods
- GET    /v1/tools/@example
+ GET    /v1/methods/example.com/list_invoices
- DELETE /v1/tools/@example/methods/{method_id}
+ DELETE /v1/methods/example.com/list_invoices
- PUT    /v1/catalog/version-preference  {"operation_id": 1820}
+ PATCH  /v1/methods/companiesmarketcap.com/get_company_size  {"pinned_version": 2}
```

`DELETE /v1/tools/{api}` deleted every operation of a tool; delete each method now. `/restore` and `/environment` are gone.

## Builds

```diff
  POST /v1/builds
  {
-   "prompt": "List my invoices on example.com",
-   "url": "https://example.com/billing",
+   "query": "List my invoices on example.com",
+   "platform": "example.com",
    "visibility": "private",
-   "connections": { "billing": "conn_01m5kvvt1pkybmt03dyvhyd5m2" },
-   "environment": { "EXAMPLE_API_KEY": "sk_live_…" }
+   "connections": ["conn_01m5kvvt1pkybmt03dyvhyd5m2"]
  }
```

- `visibility` is **required** for a new method: `"public"` (anyone can find and run it) or `"private"` (your organization only). The old default was private.
- `api` or `method_id`, to change a method, is now `method`. A key in `environment` becomes an `api_key` connection ([below](#connections)). `contribute` and `risk_acknowledgment` are gone.
- `/approvals/{approval_id}` is gone: a build that writes does its action once, for real, with the `input` you send. `/retry` is gone: send `POST /v1/builds/{id}/messages` with `{"text": "…"}`, or start a new build.

## Connections

```diff
- POST   /v1/connections/attempts {"website_url": "https://example.com"}
+ POST   /v1/connections {"platform": "example.com", "type": "session", "attest": true}
- GET    /v1/connections/attempts/{attempt_id}
+ GET    /v1/connections/{id}
- POST   /v1/connections/attempts/{attempt_id}/submit {"step_id": "…", "fields": {…}}
+ POST   /v1/connections/{id}/sign-in {"step_id": "…", "fields": {…}}
- POST   /v1/connections/attempts/{attempt_id}/retry
+ POST   /v1/connections/{id}/sign-in {"attest": true, "restart": true}
- POST   /v1/connections/attempts/{attempt_id}/cancel
+ DELETE /v1/connections/{id}/sign-in
```

A saved key is a connection too:

```diff
- PUT  /v1/variables
- {"site": "example.com", "name": "API_KEY", "value": "sk_live_…"}
+ POST /v1/connections
+ {"platform": "example.com", "type": "api_key", "api_key": "sk_live_…", "attest": true}
```

`consent` is now `"attest": true`. `challenge_id` and `/confirm` are gone: a connection turns active when its sign-in ends. `GET /v1/connections` lists sign-ins and keys alike.

## Account

```diff
- GET /v1/auth
- GET /v1/usage
+ GET /v1/account
```

`/v1/account` has the organization, credits, plan limits and the key; spending history is in Studio. Rating a call (`/feedback`) is gone.

## MCP tools

The server address is the same, and clients load the new tools when they reconnect. Update prompts or code that name the old ones:

```text
fous_search_tools                      → search
fous_run_tool                          → run
fous_run_action                        → run_action
fous_get_run, fous_get_build           → get_run
fous_get_tool, fous_delete_tool        → methods
fous_build_tool                        → build
fous_connect_account, fous_variables   → connect
fous_connections                       → connections
fous_status                            → account
```

New: `query` (describe what you want; Fous picks the methods and runs them), `stop` and `builds`.

## Until the sunset

The three old `/v1/query` endpoints answer in the old shape, run on the new system and cost the same 1 credit. Each answer carries `Deprecation`, `Sunset` (when they stop) and `Link` (this guide). Until then:

- `request_id` is the run's id with `req_` in front.
- `data.receipt.method` is the method to send `POST /v1/runs`.
- `response.format` `text` or `markdown`, `response.schema` and `response.mapping` answer `400`; `include` and `exclude` still work.
- A stream sends the `accepted` stage, then the result.

From 10 November 2026, 00:00 UTC (the `Sunset` date), they answer `410`. Questions: [hello@fous.com](mailto:hello@fous.com).
