Quickstart
- Sign in to the console with your Baguette Bot account (€1 free to try once your email is verified).
- Create a key under API keys. It starts with
bb_live_and is shown only once. - Create an agent, then give it a task:
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:
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
{
"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
| Parameter | Type | |
|---|---|---|
| name | string, required | Up to 80 characters. |
| instructions | string | Standing instructions for the agent (20,000 characters max). |
| model | string | An id from GET /v1/models. Default: anthropic/claude-haiku-5.5. |
| idle_minutes | integer 1–120 | Idle minutes before the computer shuts down. Default: 5. |
| metadata | object | Your own data (customer id…), returned as is. |
Returns 201 with the agent.
List, retrieve, update, delete
limit up to 500).name, instructions, model, idle_minutes or metadata.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”).
| Parameter | Type | |
|---|---|---|
| content | string, required | The task, in plain language (100,000 characters max). |
| wait | boolean | true: the response comes when the agent is done, up to 120 s. Otherwise an immediate 202, and you follow the agent with events. |
{
"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.
limit (default 50, max 200) and after (a message id, to read only what came next).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.
| Event | Data | |
|---|---|---|
| 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. |
| message | message | A new message (same format as the conversation). |
| message.updated | message | A message that was completed. |
| computer | { status } | The computer changes state (provisioning, running, stopped…). |
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):
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.
none, provisioning, running, stopped…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.
| Parameter | Type | |
|---|---|---|
| interactive | boolean | true: your user can take over the mouse and keyboard (a captcha, a login). View-only by default. |
| ttl_seconds | integer 60–86400 | How long the link is valid. Default: 3600. |
{ "object": "live_view", "url": "https://api.baguettebot.com/v1/live/…", "interactive": false, "expires_at": "2026-10-22T10:12:03.000Z" }<iframe src="LIVE_URL"
style="width:100%;aspect-ratio:16/10;border:0;border-radius:12px"></iframe>Files
path (e.g. ~/Uploads/invoice.pdf) and content_base64 (up to about 30 MB). Returns 201.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
eur_per_million_input_tokens, eur_per_million_output_tokens, context_length and vision, plus the computer's price.{ "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
{ "error": { "code": "insufficient_balance", "message": "…" } }| HTTP status | Meaning | |
|---|---|---|
| 400 | Invalid request | Missing or out-of-range parameter, unknown model (invalid_model). |
| 401 | Unauthenticated | Missing, invalid or revoked key (invalid_api_key). |
| 402 | Balance empty | insufficient_balance: top up in the console. |
| 404 | Not found | Agent that doesn't exist or isn't yours, file not found. |
| 409 | Conflict | The computer is off (computer_not_running). |
| 429 | Too many requests | Rate 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+)
// 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
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"])