Skip to main content
Arcanflows

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:

bash
curl -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:

bash
curl 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
HeaderRequiredDescription
AuthorizationYesBearer <jwt> (management API) or Bearer emb_... (agent calls). Agent calls also accept X-API-Key: emb_....
Content-TypeYes*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:

ParameterDefaultDescription
page1Page number
per_page20Items per page (max 100)

Example:

GET /api/v1/agents?page=2&per_page=10

HTTP Status Codes

CodeMeaning
200OK — Request succeeded
201Created — Resource created successfully
204No Content — Deletion succeeded
400Bad Request — Invalid input or malformed JSON
401Unauthorized — Missing or invalid authentication
403Forbidden — Insufficient permissions for this action
404Not Found — Resource does not exist
409Conflict — Resource already exists or state conflict
422Unprocessable Entity — Validation failed
429Too Many Requests — Rate limit exceeded
500Internal Server Error — Unexpected server failure

API Endpoint Groups

The Arcanflows API is organized into 17 sections:

#SectionBase PathDescription
1Authentication & Users/auth, /users, /api-keysLogin, MFA, user management, profiles, permissions, API keys
2Agents/agentsAgent CRUD, chat (sync/stream/async), sub-agents, training, stats, SerpAPI
3Conversations/conversationsConversation history and message retrieval
4Workflows/workflowsWorkflow CRUD, execution, debug mode, templates, node types
5Forms/formsForm CRUD, submissions, public forms, dynamic field configuration
6Data Tables/data-tablesTable/record CRUD, CSV import, field management
7Tools/toolsTool CRUD, attach tools to agents, execution logs
8Credentials/credentialsCredential vault, access control, audit trail
9LLM & Models/llm-backends, /modelsBackend configuration, model routing, inference, Ollama management
10Voice/voiceText-to-speech, speech-to-text, voice profile management
11Phone/public/phone, /public/phone/server, /phoneEmbedded webphone: pbx_ session mint, browser-side call API + ArcanPhone widget, pbxs_ server API (calls, stats, click-to-call, webhooks, seats), caller lookup — interactive reference
12Webhooks & Events/webhooksOutgoing/incoming webhooks, event subscriptions
13Notifications/notificationsNotification channels and user preferences
14Scheduled Tasks/scheduled-tasksCron-based recurring task management
15Storage/storageFile upload, download, and management
16Infrastructure/infrastructureContainer management, system health checks
17Swagger Reference/swagger/index.htmlFull 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

javascript
const 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

python
import 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