Connect
Set up the API
Every tool is a REST endpoint under http://agents.botify.com. The request shape is the same
for all of them, so once you have called one you have called them all — only the
item and config schemas change.
Authentication
All processing endpoints require a Botify API token. Send it as a bearer token, or in the
X-Botify-Api-Token header if that fits your client better.
Authorization: Bearer <YOUR_BOTIFY_API_TOKEN>
# or
X-Botify-Api-Token: <YOUR_BOTIFY_API_TOKEN>
URL shape
organization and project are the Botify slugs the call runs
against; the tool reads the project's data with your permissions.
http://agents.botify.com/{organization}/{project}/{tool}/process
Processing modes
| Endpoint | Kind | Use it for |
|---|---|---|
/process |
Synchronous | One item, answer in the response. |
/batch_process |
Synchronous | Several items in one round-trip. |
/async_process |
Asynchronous | One item that takes longer than an HTTP timeout allows. |
/async_batch_process |
Asynchronous | Large jobs, streamed in as JSONL. |
The asynchronous endpoints only exist on tools that opt into them; the tool page tells you which ones do.
Process a single item
curl -X POST "http://agents.botify.com/{organization}/{project}/calculator/process" \
-H "Authorization: Bearer $BOTIFY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"config": {},
"item": {}
}'
import os
import httpx
BASE_URL = "http://agents.botify.com"
TOKEN = os.environ["BOTIFY_API_TOKEN"]
def process(organization: str, project: str, tool: str, item: dict, config: dict | None = None):
response = httpx.post(
f"{BASE_URL}/{organization}/{project}/{tool}/process",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"item": item, "config": config or {}},
timeout=300,
)
response.raise_for_status()
return response.json()
print(process("my-org", "my-project", "calculator", {}))
const BASE_URL = "http://agents.botify.com";
const TOKEN = process.env.BOTIFY_API_TOKEN;
async function runTool(organization, project, tool, item, config = {}) {
const response = await fetch(
`${BASE_URL}/${organization}/${project}/${tool}/process`,
{
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ item, config }),
},
);
if (!response.ok) throw new Error(await response.text());
return response.json();
}
console.log(await runTool("my-org", "my-project", "calculator", {}));
Process many items
batch_process takes an items array and returns one result per item,
in the same order. A single failing item does not fail the batch: its slot holds an error
object instead.
curl -X POST "http://agents.botify.com/{organization}/{project}/calculator/batch_process" \
-H "Authorization: Bearer $BOTIFY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"config": {},
"items": [{}, {}]
}'
Run a long job in the background
Submit, then poll. HEAD is the cheap way to ask "is it done?" — it answers
200 when results are ready and 202 while the job is still running.
# 1. submit
curl -X POST "http://agents.botify.com/{organization}/{project}/calculator/async_process" \
-H "Authorization: Bearer $BOTIFY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"config": {}, "item": {}}'
# => {"batch_id": "abc123"}
# 2. poll
curl -I -X HEAD "http://agents.botify.com/{organization}/{project}/calculator/async_batches/abc123" \
-H "Authorization: Bearer $BOTIFY_API_TOKEN"
# 200 = ready, 202 = still processing, 404 = unknown batch
# 3. read the result
curl "http://agents.botify.com/{organization}/{project}/calculator/async_batches/abc123/single" \
-H "Authorization: Bearer $BOTIFY_API_TOKEN"
For many items, submit to /async_batch_process as JSONL — first line holds
config and batch_config, then one line per item — and read all
results from /async_batches/{batch_id}.
Errors
| Status | Meaning |
|---|---|
400 |
The payload, the token or the organization/project pair is not usable. |
403 |
The token is valid but has no access to this project or tool. |
404 |
Unknown tool, or a batch id that does not exist. |
500 |
Processing failed on our side. The body carries an error id worth reporting. |
Discovering tools programmatically
Rather than hardcoding a list, read the catalog. It carries the JSON schemas for
item, config and the response, which is enough to generate forms
or LLM tool definitions.
curl "http://agents.botify.com/agents" # every published tool
curl "http://agents.botify.com/agents?mcp=1" # only the ones exposed over MCP
curl "http://agents.botify.com/agents/calculator" # one tool, with its schemas