API Reference
REST API
Create agents, send prompts, poll runs and read events over HTTP
The REST API is served under https://run.camelai.com/v1. The full
specification is /v1/openapi.json
(OpenAPI 3). Every request sends Authorization: Bearer <API key>; see
Authentication.
The SDKs wrap all of this, including tool calls over the agent's own connection, which REST alone can't serve. Use REST for languages without an SDK, and for scripts.
Create an agent
curl https://run.camelai.com/v1/agents \
-H "Authorization: Bearer $CAMELAI_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: support-triage" \
-d '{"model": "anthropic/claude-sonnet-5-5", "systemPrompt": "Be concise.", "builtins": ["web_search"]}'{"id": "client_...", "token": "...", "expiresAt": null}The Idempotency-Key is the agent's key: the same key returns the same agent,
brought to the configuration you send. The body takes name, model,
systemPrompt, systemPromptAppend, thinkingLevel, builtins, definition,
subject, context, keyScope, spendLimit, modelHeaders, mounts,
fileTools, ttlSeconds and initialMessages.
It also takes prompt, a first message with the same body as
POST /v1/agents/{id}/prompt. The answer then carries prompt: the request to
poll, or {error} if it was refused. The agent is made either way.
Send a message and get the result
curl https://run.camelai.com/v1/agents/$AGENT/prompt \
-H "Authorization: Bearer $CAMELAI_API_KEY" -H "Content-Type: application/json" \
-d '{"text": "Which tickets look urgent?", "requestId": "msg-8812", "from": {"id": "u_42", "name": "Ada"}}'The prompt answers 202 with the request record. requestId is optional; it
makes the prompt idempotent, so sending the same one again returns the same run.
Other fields are files, metadata, whileRunning (queue or steer),
spendLimit and allowDisconnected.
Poll the request until state is completed:
curl https://run.camelai.com/v1/agents/$AGENT/requests/msg-8812 \
-H "Authorization: Bearer $CAMELAI_API_KEY"{"id": "msg-8812", "method": "prompt", "state": "completed",
"outcome": {"result": {"reply": "Tickets 4411 and 4417...", "replyIndex": 5, "messages": 6,
"error": null, "files": [], "toolErrors": []}}}An ended request with error set failed; stopped: "input_required" means it
waits on a person. See Run outcomes. Instead of
polling, you can register a webhook for run.completed
and run.failed.
Endpoints
Conventions
- Errors are
{"error": "<message>", "code": "<CODE>"}. Switch oncode, not the message. See Errors. - Every POST that changes something takes an
Idempotency-Keyheader. A retry with the same key, path and body gets the first answer again, for 24 hours. - Every 429 and 503 has
Retry-After.