API Reference
Complete REST API reference for integrating with the Arcanflows platform.
Base URL
Arcanflows is a self-hosted platform. All API requests use your instance URL:
https://your-instance.arcanflows.com/api/v1
Replace your-instance.arcanflows.com with the actual hostname of your deployment. All examples in this documentation use this placeholder.
Authentication
There are two ways to authenticate, depending on what you're doing:
1. Embed API Key — to call an agent from outside
To send a message to an agent from your own code, create an Embed API Key on the agent's Embed Settings tab (/agents/{id}/embed). It starts with emb_ and is shown in full only once. Send it as a bearer token, an X-API-Key header, or an ?api_key= query parameter:
bashcurl -X POST https://your-instance.arcanflows.com/api/v1/public/agents/AGENT_ID/chat \ -H "Authorization: Bearer emb_your_key_here" \ -H "Content-Type: application/json" \ -d '{"session_id": "user-42", "message": "Hello!"}'
Each Embed key authorizes one specific agent, and the tenant is derived from the key.
⚠️ Two different "API keys" — don't confuse them. The Embed API Key (
emb_, from Embed Settings) authenticates your calls to an agent. The keys under Settings → API Keys are Provider API Keys (your OpenAI/Anthropic credentials,sk-…) that let the platform call the LLM on your behalf — they are never used to authenticate API requests.
2. JWT Bearer Token — for the management API
To manage resources (create agents, run workflows, query data tables, etc.), log in with POST /api/v1/auth/login to get a JWT access_token, and send it as a bearer token. Your user and tenant are derived from the token:
bashcurl https://your-instance.arcanflows.com/api/v1/agents \ -H "Authorization: Bearer <your_login_jwt>"
See the Authentication & Users page for login flows, MFA, refresh tokens, and Embed key management.
Calling an agent (the public agent API)
The most common integration is sending a message to an agent. Authenticate with an Embed API Key (above):
POST /api/v1/public/agents/{AGENT_ID}/chat
Request body: session_id (required — a stable id for the conversation thread) and message (required). Optionally conversation_id to continue a specific thread, and visitor_* metadata.
Response (200): the answer is in assistant_reply.content; token usage is on the message objects.
json{ "conversation_id": "550e8400-…", "user_message": { "role": "user", "content": "Hello!" }, "assistant_reply": { "role": "assistant", "content": "Hi! How can I help?", "input_tokens": 45, "output_tokens": 120 } }
Streaming: POST /api/v1/public/agents/{AGENT_ID}/chat/stream returns Server-Sent Events — a metadata event (with conversation_id and RAG sources), chunk events (append each delta), and a final done event with the full content.
History: GET /api/v1/public/agents/{AGENT_ID}/conversations?session_id=… (or /conversations/{ID}) returns the thread with its messages array.
Full walkthrough with all fields and language examples: Using the API guide (in the docs assistant), and the Agents API page.
Request Format
- All request bodies must be JSON with
Content-Type: application/json - File uploads use
multipart/form-data - Query parameters are used for filtering, pagination, and sorting
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <jwt> (management API) or Bearer emb_... (agent calls). Agent calls also accept X-API-Key: emb_.... |
Content-Type | Yes* | application/json for request bodies |
Response Format
Single Resource
json{ "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Support Bot", "status": "published", "created_at": "2026-03-15T10:30:00Z", "updated_at": "2026-03-15T14:20:00Z" }
List Response (Paginated)
json{ "data": [ { "id": "...", "name": "Agent 1" }, { "id": "...", "name": "Agent 2" } ], "pagination": { "page": 1, "per_page": 20, "total": 42, "total_pages": 3 } }
Error Response
Non-2xx responses return a short error and a human-readable message:
json{ "error": "Unauthorized", "message": "Invalid or expired token" }
For example, calling an agent with a missing Embed key returns 401 { "error": "Unauthorized", "message": "API key required" }; an invalid or wrong-agent key returns 403 { "error": "Forbidden", "message": "…" }.
Pagination
List endpoints accept these query parameters:
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number |
per_page | 20 | Items per page (max 100) |
Example:
GET /api/v1/agents?page=2&per_page=10
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | OK — Request succeeded |
201 | Created — Resource created successfully |
204 | No Content — Deletion succeeded |
400 | Bad Request — Invalid input or malformed JSON |
401 | Unauthorized — Missing or invalid authentication |
403 | Forbidden — Insufficient permissions for this action |
404 | Not Found — Resource does not exist |
409 | Conflict — Resource already exists or state conflict |
422 | Unprocessable Entity — Validation failed |
429 | Too Many Requests — Rate limit exceeded |
500 | Internal Server Error — Unexpected server failure |
API Endpoint Groups
The Arcanflows API is organized into 17 sections:
| # | Section | Base Path | Description |
|---|---|---|---|
| 1 | Authentication & Users | /auth, /users, /api-keys | Login, MFA, user management, profiles, permissions, API keys |
| 2 | Agents | /agents | Agent CRUD, chat (sync/stream/async), sub-agents, training, stats, SerpAPI |
| 3 | Conversations | /conversations | Conversation history and message retrieval |
| 4 | Workflows | /workflows | Workflow CRUD, execution, debug mode, templates, node types |
| 5 | Forms | /forms | Form CRUD, submissions, public forms, dynamic field configuration |
| 6 | Data Tables | /data-tables | Table/record CRUD, CSV import, field management |
| 7 | Tools | /tools | Tool CRUD, attach tools to agents, execution logs |
| 8 | Credentials | /credentials | Credential vault, access control, audit trail |
| 9 | LLM & Models | /llm-backends, /models | Backend configuration, model routing, inference, Ollama management |
| 10 | Voice | /voice | Text-to-speech, speech-to-text, voice profile management |
| 11 | Phone | /public/phone, /public/phone/server, /phone | Embedded webphone: pbx_ session mint, browser-side call API + ArcanPhone widget, pbxs_ server API (calls, stats, click-to-call, webhooks, seats), caller lookup — interactive reference |
| 12 | Webhooks & Events | /webhooks | Outgoing/incoming webhooks, event subscriptions |
| 13 | Notifications | /notifications | Notification channels and user preferences |
| 14 | Scheduled Tasks | /scheduled-tasks | Cron-based recurring task management |
| 15 | Storage | /storage | File upload, download, and management |
| 16 | Infrastructure | /infrastructure | Container management, system health checks |
| 17 | Swagger Reference | /swagger/index.html | Full interactive OpenAPI documentation |
Code Examples
cURL — call an agent (Embed key)
bash# Send a message; the reply is in assistant_reply.content curl -X POST https://your-instance.arcanflows.com/api/v1/public/agents/AGENT_ID/chat \ -H "Authorization: Bearer emb_your_key" \ -H "Content-Type: application/json" \ -d '{"session_id": "user-42", "message": "Hello, how can you help me?"}'
cURL — manage resources (JWT)
bash# List published agents curl "https://your-instance.arcanflows.com/api/v1/agents?status=published" \ -H "Authorization: Bearer <your_login_jwt>" # Create an agent curl -X POST https://your-instance.arcanflows.com/api/v1/agents \ -H "Authorization: Bearer <your_login_jwt>" \ -H "Content-Type: application/json" \ -d '{ "name": "Support Bot", "primary_model": "gpt-4o", "system_prompt": "You are a helpful support assistant." }'
JavaScript (fetch) — call an agent
javascriptconst BASE_URL = "https://your-instance.arcanflows.com/api/v1"; const EMBED_KEY = "emb_your_key"; // keep this server-side, never in the browser const res = await fetch(\`\${BASE_URL}/public/agents/\${agentId}/chat\`, { method: "POST", headers: { "Authorization": \`Bearer \${EMBED_KEY}\`, "Content-Type": "application/json", }, body: JSON.stringify({ session_id: "user-42", message: "Hello!" }), }); const data = await res.json(); console.log(data.assistant_reply.content);
Python (requests) — call an agent
pythonimport requests BASE_URL = "https://your-instance.arcanflows.com/api/v1" EMBED_KEY = "emb_your_key" # keep server-side r = requests.post( f"{BASE_URL}/public/agents/{agent_id}/chat", headers={"Authorization": f"Bearer {EMBED_KEY}", "Content-Type": "application/json"}, json={"session_id": "user-42", "message": "Hello!"}, ) print(r.json()["assistant_reply"]["content"])
Rate Limiting
API requests are rate-limited per IP (or per authenticated user) — 1000 requests/minute by default, plus tighter limits on sensitive endpoints (e.g. login, form submit). Responses include X-RateLimit-Limit / X-RateLimit-Remaining headers; when you exceed the limit you get a 429 with a Retry-After header — wait that many seconds and retry.
See Rate Limits for full details and best practices.
Interactive API Reference
A full interactive Swagger UI is available at:
https://your-instance.arcanflows.com/swagger/index.html
The Swagger reference includes every endpoint, request/response schemas, and a "Try it out" feature for testing directly in the browser.
The phone API (embedded webphone, pbx_ / session token / pbxs_ keys) also ships its own public, unauthenticated OpenAPI document at /api/v1/public/phone/openapi.json, rendered on this site at Phone API Reference — start with the Phone API quickstart.
Next Steps
- Authentication & Users — API keys, login, MFA, user management
- Agents API — Create agents, chat, streaming, sub-agents
- Workflows API — Build and execute automation workflows
- Webhooks & Events — Receive real-time event notifications
- Phone API — Embed the webphone in your CRM, click-to-call, call data and phone events