> ## Documentation Index
> Fetch the complete documentation index at: https://anything.notte.cc/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Building an API

> From a sentence to a deployed endpoint.

Describe a web task in the composer. An agent gets a sandbox with a real browser, works out how the site serves its data, writes the Python behind your API, and deploys it. Takes **2 to 10 minutes**.

Building from code? See [Streaming builds](https://anything.notte.cc/docs/build-streaming.md) for request examples, progress events, verified completion, and detached mode.

## Write a good prompt

Say three things: which site, what goes in, what comes out.

| Weak | Better |
| - | - |
| "Scrape Zillow" | "Given a zip code, return Zillow listings with price, beds, and sqft" |
| "Get GitHub trending" | "Return this week's trending repos with name, language, and star delta" |

The fields you name become the response schema. Anything you phrase as an input becomes a parameter; anything you hard-code stays hard-coded.

## While it works

The thread streams the agent's work and sometimes needs you: it shows the live browser, asks questions when the task is ambiguous, waits for approval on actions that touch your accounts, and prompts you to connect an app if the task needs one.

The composer has a model picker (Sonnet, GPT-5.6, Grok, DeepSeek, GLM, and others). Sonnet 4.6 is the default and the safe answer.

## Iterating

Reply in the same thread: "also return the listing URL", "make `max_results` a parameter", "prices should be numbers, not strings". Each accepted change deploys a new version.

## Versions

Every deploy is stamped like `v20260824_142124`. The **Versions** tab shows the code behind each one and lets you roll back. Callers keep the same `function_id`.

## Self-healing

Sites change. When a run comes back with a traceback, the thread that built the API wakes up, re-maps the page, and deploys a fix if it can. Toggle it per API on the **Self-heal** tab, which also lists every attempt.

> [!NOTE]
>
> It only fires on a returned traceback, which is the API's own failure. Wrong variable names are your side of the contract, and a platform outage is neither.

## When a build does not work

Hard login walls and aggressive bot defences are genuinely hard. When the agent cannot get a clean, repeatable result it says so rather than deploying something that fails silently later.

## Build in the background

Start a build with `POST /api/anything/start`, a Notte API key in the `Authorization: Bearer ...` header, and this body:

```json theme={"system"}
{
  "query": "Build a private API that returns the current price for a product URL.",
  "version": "v2",
  "detach": true,
  "thread_id": "a8259413-58c3-4dfb-8993-b9caa13bc4fa"
}
```

Generate and save a new UUID for `thread_id` before submitting. A new thread is created when that ID does not exist. The API returns `202` with `thread_id`, `url`, and `status: "started"`. The build continues on the server after the client disconnects, including when its browser quits.

To check it later, use the same workspace's API key with these read-only endpoints:

| Endpoint | What it returns |
| - | - |
| `GET /api/threads/{thread_id}/activity` | `working`, `needsInput`, and `error` flags. |
| `GET /api/threads/{thread_id}/sandbox/v2/messages?limit=100` | The saved transcript, including message `blocks`, `metadata`, and `nextCursor` for older pages. |

A successful, tested build has a `complete_build` tool call followed by a successful tool result containing `status: "build_completed"`, the matching `thread_id`, `function_id`, and `version`. A function upload or text saying it finished is not the same completion signal. Activity flags describe the thread, not the build result: `needsInput` can also mark the optional marketplace listing offer after a successful build.

Poll these reads while the application is open, and read again after reconnecting. An authentication or network error does not mean the build failed. If the start response was lost, check the saved thread ID before retrying. Sending another POST starts another turn; `thread_id` is a thread address, not an idempotency key.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.