← API overview
v1 · REST · JSON

API documentation

The Baguette Bot API creates AI agents that work on their own cloud computer (Linux desktop, Chrome, terminal, files). You send a task in plain language, the agent carries it out on its computer and returns the result, with a live screen you can embed in your app. A JSON REST API, no SDK required.

Quickstart

  1. Sign in to the console with your Baguette Bot account (€1 free to try once your email is verified).
  2. Create a key under API keys. It starts with bb_live_ and is shown only once.
  3. Create an agent, then give it a task:
bash
export KEY=bb_live_…

# 1. An agent (its computer boots on its first task)
curl https://api.baguettebot.com/v1/agents -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name": "Price watch", "instructions": "Answer in English, with a table."}'

# 2. A task, and the answer once it's done (up to 120 s)
curl https://api.baguettebot.com/v1/agents/AGENT_ID/messages -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"content": "Compare the price of the PS5 on Amazon, Argos and Currys", "wait": true}'

Authentication

Every request carries your key in the Authorization header:

http
Authorization: Bearer bb_live_…

Base URL: https://api.baguettebot.com. Request and response bodies are JSON (Content-Type: application/json). Keep the key on your server: never in a mobile app or in a web page's code. A key revoked in the console stops working immediately.

Agents

An agent has a name, instructions (its role, how to answer…), an AI model, a memory and its own computer, isolated from other agents. Its files and browser sessions persist between tasks until you delete it.

The agent object

json
{
  "id": "6f1c2a8e-…",
  "object": "agent",
  "name": "Shopping assistant",
  "model": "anthropic/claude-haiku-5.5",
  "instructions": "…",
  "status": "idle",            // idle | working | blocked
  "status_text": null,
  "computer": { "status": "stopped" },
  "idle_minutes": 5,
  "metadata": { "customer_id": "c_42" },
  "created_at": "2026-10-22T09:12:03.000Z"
}

Create an agent

POST /v1/agents

ParameterType
namestring, requiredUp to 80 characters.
instructionsstringStanding instructions for the agent (20,000 characters max).
modelstringAn id from GET /v1/models. Default: anthropic/claude-haiku-5.5.
idle_minutesinteger 1–120Idle minutes before the computer shuts down. Default: 5.
metadataobjectYour own data (customer id…), returned as is.

Returns 201 with the agent.

List, retrieve, update, delete

GET/v1/agents
Your agents, newest first (limit up to 500).
GET/v1/agents/{id}
One agent, with its status and its computer's.
PATCH/v1/agents/{id}
Change name, instructions, model, idle_minutes or metadata.
DELETE/v1/agents/{id}
Deletes the agent, its conversation and its computer (files included). Cannot be undone.

Tasks and messages

POST /v1/agents/{id}/messages gives the agent a task or a message. It picks up the conversation where it left off, so you can chain requests (“now export it as a PDF”).

ParameterType
contentstring, requiredThe task, in plain language (100,000 characters max).
waitbooleantrue: the response comes when the agent is done, up to 120 s. Otherwise an immediate 202, and you follow the agent with events.
json
{
  "object": "run",
  "agent_id": "6f1c2a8e-…",
  "message_id": "b2e0…",
  "status": "done",            // done | working (still running after 120 s)
  "output": "| Shop | Price |\n|---|---|\n| … |",
  "messages": [
    { "id": "…", "role": "assistant", "content": null, "tool_calls": [{ "name": "browser", "summary": "…" }], "created_at": "…" },
    { "id": "…", "role": "tool", "content": "…", "tool": { "name": "browser", "ok": true, "summary": "…" }, "created_at": "…" },
    { "id": "…", "role": "assistant", "content": "| Shop | Price | …", "created_at": "…" }
  ]
}

output is the agent's last answer (Markdown). If the task takes longer than 120 s, status is working: follow it with GET /v1/agents/{id}/events or read the conversation again.

GET/v1/agents/{id}/messages
The conversation: limit (default 50, max 200) and after (a message id, to read only what came next).
POST/v1/agents/{id}/stop
Stops the current task.

Message roles: user (your requests), assistant (the agent; tool_calls summarises the actions it starts), tool (an action's result, with tool.name, tool.ok and tool.summary), event (system notices, such as an empty balance).

Live events

GET /v1/agents/{id}/events opens a Server-Sent Events stream (text/event-stream): everything the agent does, in real time. A : ping comment arrives every 15 s to keep the connection open.

EventData
ready{ agent_id }The stream is open.
status{ status, text }working, idle or blocked, with what the agent is doing.
delta{ message_id, text }A piece of the answer being written.
messagemessageA new message (same format as the conversation).
message.updatedmessageA message that was completed.
computer{ status }The computer changes state (provisioning, running, stopped…).
text
event: ready
data: {"agent_id":"6f1c2a8e-…"}

event: status
data: {"status":"working","text":"…"}

event: delta
data: {"message_id":"…","text":"The cheapest"}

event: message
data: {"id":"…","role":"tool","content":"…","tool":{"name":"browser","ok":true,"summary":"…"},"created_at":"…"}

event: computer
data: {"status":"running"}

Reading the stream in Node (the authorization header rules out the browser's EventSource: relay the stream from your server):

javascript
const res = await fetch("https://api.baguettebot.com/v1/agents/" + agentId + "/events", {
  headers: { Authorization: "Bearer " + process.env.BAGUETTE_API_KEY },
});
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
let buffer = "";
for (;;) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += value;
  let i;
  while ((i = buffer.indexOf("\n\n")) !== -1) {
    const chunk = buffer.slice(0, i); buffer = buffer.slice(i + 2);
    const type = /^event: (.+)$/m.exec(chunk)?.[1];
    const data = /^data: (.+)$/m.exec(chunk)?.[1];
    if (type && data) console.log(type, JSON.parse(data));
  }
}

The agent's computer

Every agent has a Linux computer (1280×800 desktop, Chrome, terminal, a user with sudo). It boots on its own on the first task, in a few seconds, and shuts down after idle_minutes without activity. Its files are kept while it is off. Cookie banners are declined automatically.

GET/v1/agents/{id}/computer
Its state: none, provisioning, running, stopped…
POST/v1/agents/{id}/computer/start
Boot it ahead of time (so it's ready for the first task).
POST/v1/agents/{id}/computer/stop
Shut it down now (billing stops).
GET/v1/agents/{id}/computer/screenshot
A JPEG screenshot (409 when it's off).

Show the screen in your app

POST /v1/agents/{id}/computer/live creates a signed, expiring link to the agent's screen, to embed in an iframe. Create it on your server and only hand the URL to your page: it doesn't contain your key.

ParameterType
interactivebooleantrue: your user can take over the mouse and keyboard (a captcha, a login). View-only by default.
ttl_secondsinteger 60–86400How long the link is valid. Default: 3600.
json
{ "object": "live_view", "url": "https://api.baguettebot.com/v1/live/…", "interactive": false, "expires_at": "2026-10-22T10:12:03.000Z" }
html
<iframe src="LIVE_URL"
  style="width:100%;aspect-ratio:16/10;border:0;border-radius:12px"></iframe>

Files

POST/v1/agents/{id}/files
Uploads a file: path (e.g. ~/Uploads/invoice.pdf) and content_base64 (up to about 30 MB). Returns 201.
GET/v1/agents/{id}/files?path=…
Downloads a file from the computer (something the agent produced or downloaded), as binary.

Both routes boot the computer if it's off. Mention the file's path in your task so the agent uses it (“the file is in ~/Uploads/invoice.pdf”), or ask it where it saved what it produced.

Models and balance

GET/v1/models
Available models (300+: Claude, GPT, Gemini, Mistral, DeepSeek…) with eur_per_million_input_tokens, eur_per_million_output_tokens, context_length and vision, plus the computer's price.
GET/v1/account
Your balance: { "balance_eur": 12.37, "currency": "eur" }.

A model with vision: true sees its computer's screen; the others work from the pages' text, which is enough for most web tasks.

Pricing

No subscription: a prepaid balance in euros, topped up in the console (from €20: €20, €50, €100 or any amount you choose), that never expires.

  • AI model: by tokens used, at the model's price per million tokens (GET /v1/models).
  • Computer: €2 per hour while it's on, billed per second.

When the balance runs out, tasks stop and the API returns 402. The console shows what each agent costs.

Errors and limits

json
{ "error": { "code": "insufficient_balance", "message": "…" } }
HTTP statusMeaning
400Invalid requestMissing or out-of-range parameter, unknown model (invalid_model).
401UnauthenticatedMissing, invalid or revoked key (invalid_api_key).
402Balance emptyinsufficient_balance: top up in the console.
404Not foundAgent that doesn't exist or isn't yours, file not found.
409ConflictThe computer is off (computer_not_running).
429Too many requestsRate limit exceeded, or maximum number of agents reached (too_many_agents).

Error messages are currently in French; rely on error.code in your code.

  • 600 requests per minute per IP address, including 60 agent creations and 120 tasks.
  • 200 agents per account: delete the ones you no longer use.
  • Agents don't send emails or make phone calls. Use must follow our terms: no spam, fraud, abusive collection of personal data or attacks on websites.

Complete examples

JavaScript (Node 18+)

javascript
// Node 18+
const KEY = process.env.BAGUETTE_API_KEY;
const api = (path, body, method = body ? "POST" : "GET") =>
  fetch("https://api.baguettebot.com" + path, {
    method,
    headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
    body: body && JSON.stringify(body),
  }).then(async (r) => {
    if (!r.ok) throw new Error((await r.json()).error?.message ?? r.statusText);
    return r.json();
  });

const agent = await api("/v1/agents", { name: "Assistant", model: "anthropic/claude-haiku-5.5" });
const run = await api(`/v1/agents/${agent.id}/messages`, { content: "…", wait: true });
console.log(run.output);

Python

python
import os, requests

API = "https://api.baguettebot.com"
H = {"Authorization": f"Bearer {os.environ['BAGUETTE_API_KEY']}"}

agent = requests.post(f"{API}/v1/agents", headers=H, json={"name": "Assistant"}).json()
run = requests.post(f"{API}/v1/agents/{agent['id']}/messages", headers=H,
                    json={"content": "…", "wait": True}, timeout=150).json()
print(run["output"])