Complete reference for the Arkon API. All endpoints return JSON.
Arkon uses two types of tokens:
Used for dashboard access and management endpoints. Set via MC_ADMIN_TOKEN in .env.local.
Authorization: Bearer YOUR_ADMIN_TOKEN
Or via cookie (mc_auth) for browser sessions. CSRF protection requires x-csrf-token header for state-changing requests.
Used for event ingestion. Set via MC_AGENT_TOKENS in .env.local as comma-separated tenant:token pairs.
Authorization: Bearer YOUR_AGENT_TOKEN
All endpoints return errors in this format:
{
"error": "Description of what went wrong"
}Common status codes: 401 (unauthorized), 400 (bad request), 404 (not found), 429 (rate limited), 500 (server error).
Send events from your agents to Arkon. This is the primary integration point.
Auth: Agent token
Request body:
{
event_type: "message_received" | "message_sent" | "tool_call" | "error" | "cron" | "system" | "note";
direction?: "inbound" | "outbound";
session_key?: string; // Group events into sessions
channel_id?: string; // Source channel (telegram, discord, etc.)
sender?: string; // Who sent the message
content?: string; // Message content (auto-scanned by ThreatGuard)
metadata?: {
model?: string; // Model name (e.g., "claude-sonnet-4-6")
tokens?: number; // Total token count
input_tokens?: number; // Input tokens
output_tokens?: number; // Output tokens
tool_name?: string; // For tool_call events
[key: string]: unknown; // Any additional metadata
};
token_estimate?: number; // Token count (alternative to metadata.tokens)
timestamp?: string; // ISO 8601 (defaults to server time)
}Response (201):
{
"ok": true,
"id": 12345,
"created_at": "2026-03-17T10:30:00.000Z",
"threat": {
"level": "none" | "low" | "medium" | "high" | "critical",
"classes": ["prompt_injection", "shell_command", "credential_leak"],
"matches": 0
}
}Rate limit: Per-agent, returns 429 with retryAfterSeconds: 60 when exceeded.
Example:
curl -X POST https://your-arkon-url/api/ingest \
-H "Authorization: Bearer default:your-token" \
-H "Content-Type: application/json" \
-d '{
"event_type": "message_sent",
"content": "Processed customer request about billing",
"metadata": {
"model": "claude-sonnet-4-6",
"tokens": 1250,
"input_tokens": 800,
"output_tokens": 450,
"channel": "telegram"
}
}'Overview data for the main dashboard — agents, today's stats, tenants.
Auth: Admin token
Response:
{
"agents": [
{
"id": "uuid",
"name": "my-agent",
"metadata": {},
"created_at": "2026-03-01T00:00:00Z",
"tenant_id": "default",
"last_active": "2026-03-17T10:30:00Z",
"events_24h": 47,
"events_7d": 312,
"events_total": 2100,
"tokens_24h": 125000,
"threats_30d": 2,
"cost_30d": 12.50
}
],
"todayStats": [
{
"agent_id": "uuid",
"tenant_id": "default",
"received": 23,
"sent": 24,
"tools": 8,
"errors": 1,
"tokens": 62000
}
],
"tenants": [
{ "id": "default", "name": "Default", "domain": null, "plan": "free", "created_at": "2026-03-01T00:00:00Z" }
],
"timestamp": "2026-03-17T10:30:00Z"
}Trend data over time.
Auth: Admin token
Query params: range (7d | 30d), tenant_id (optional)
Recent activity events.
Auth: Admin token
Detailed agent profile data — 30d cost, threats, error rate, top tools, recent sessions.
Auth: Admin token
Threat events with filtering and pagination.
Auth: Admin token
Query params: threat_class, severity, agent_id, limit, offset, show_dismissed (bool)
Permanently delete a threat event.
Auth: Admin token
Response:
{
"purged": true,
"content_hash": "sha256...",
"audit_logged": true
}Replace sensitive content with [REDACTED-class] placeholders.
Auth: Admin token
Response:
{
"redacted": true,
"patterns_matched": ["credential_leak"],
"redacted_count": 2
}Mark a threat as a false positive.
Auth: Admin token
Purge multiple events at once (max 100).
Auth: Admin token
Body: { "ids": [1, 2, 3] }
List all registered agents.
Auth: Admin token
Register a new agent.
Auth: Admin token Body:
{
"name": "my-new-agent",
"tenant_id": "default",
"metadata": {
"framework": "openclaw",
"description": "Customer support agent"
}
}Emergency stop an active agent run.
Auth: Admin token
Body: { "reason": "optional explanation" }
Pause an active agent run.
Auth: Admin token
Resume a paused agent run.
Auth: Admin token
List all currently active agent runs.
Auth: Admin token
Cost summary — today, 7d, 30d, projections, anomalies.
Auth: Admin token
Per-agent cost breakdown.
Auth: Admin token
Query params: range (7d | 30d), tenant_id
Per-model cost breakdown.
Auth: Admin token
Query params: range (7d | 30d)
List all workflows.
Auth: Admin token
Query params: status (active | draft | disabled | all), tenant_id
Create a new workflow.
Auth: Admin token Body:
{
"name": "Health Check",
"description": "Monitor servers every 5 minutes",
"status": "draft",
"trigger_type": "cron",
"trigger_config": { "expression": "*/5 * * * *" },
"nodes": [],
"edges": [],
"tenant_id": "default"
}Get workflow details including nodes and edges.
Auth: Admin token
Update a workflow.
Auth: Admin token
Delete a workflow.
Auth: Admin token
Manually trigger a workflow run.
Auth: Admin token
List run history for a workflow.
Auth: Admin token
List notifications for the current tenant.
Auth: Admin token
Query params: unread_only (bool), limit (max 100), offset
Response:
{
"notifications": [
{
"id": 1,
"type": "threat",
"severity": "high",
"title": "Credential leak detected",
"body": "Agent 'my-agent' exposed an API key in output",
"link": "/security",
"read": false,
"created_at": "2026-03-17T10:30:00Z"
}
],
"unread_count": 3
}Mark notifications as read.
Auth: Admin token
Body: { "ids": [1, 2, 3] } or { "all": true }
Get notification channel configuration.
Auth: Admin token
Save notification channel configuration.
Auth: Admin token Body:
{
"channels": {
"telegram": {
"enabled": true,
"config": { "bot_token": "...", "chat_id": "..." },
"types": ["threat", "anomaly", "budget"]
},
"slack": {
"enabled": false,
"config": { "webhook_url": "" },
"types": []
}
}
}Send a test notification to a configured channel.
Auth: Admin token
Body: { "channel": "telegram" }
List all monitored infrastructure nodes.
Auth: Admin token
Register a new infrastructure node.
Auth: Admin token
Get node details and recent metrics.
Auth: Admin token
Push metrics from a node (used by reporter scripts).
Auth: Admin token Body:
{
"hostname": "my-server",
"cpu_percent": 45.2,
"memory_percent": 62.1,
"disk_percent": 38,
"services": [
{ "name": "openclaw", "port": 18789, "status": "running" }
]
}Trigger SSH-based metric collection for remote nodes.
Auth: Admin token + CRON_SECRET
List approval requests.
Auth: Admin token
Query params: status (pending | approved | rejected | expired | all), limit
Approve or reject a request.
Auth: Admin token
Body: { "status": "approved" | "rejected", "reviewer_note": "optional" }
Search the audit log.
Auth: Admin token
Query params: action, actor, resource_type, from, to, limit, offset
Export data as CSV.
Auth: Admin token
Query params: type (audit_log | events), from, to, format (csv)
GDPR data purge for a specific entity.
Auth: Admin token
Body: { "entity_type": "agent" | "tenant", "entity_id": "uuid" }
Performance metrics for all agents.
Auth: Admin token
Side-by-side comparison of selected agents.
Auth: Admin token
Query params: agents (comma-separated IDs)
Gateway usage statistics.
Auth: Admin token
Query params: range (1h | 24h | 7d)
Export gateway configuration (e.g., for Claude Code integration).
Auth: Admin token
Query params: format (claude-code)
Proxy a request to an MCP server.
Auth: Admin token
Dashboard data for the authenticated client tenant.
Auth: Client token (via cookie)
List agents for the authenticated client tenant.
Auth: Client token
Cost data for the authenticated client tenant.
Auth: Client token
List client intake form submissions.
Auth: Admin token
Submit a new intake form (public endpoint).
Body:
{
"full_name": "John Doe",
"email": "john@example.com",
"priorities": "Cost reduction, better response time",
"automation_wish": "Auto-respond to support tickets",
"channels": ["telegram", "discord"]
}Check if initial setup has been completed.
Auth: None (public)
Response: { "needs_setup": true | false }
Complete the setup wizard.
Auth: None (only works when needs_setup is true)
Health check endpoint.
Auth: None (public)
Response: { "status": "ok", "timestamp": "2026-03-17T10:30:00Z" }
When Arkon sends notifications to webhook channels, the payload format is:
{
"type": "threat" | "anomaly" | "approval" | "budget" | "agent_offline" | "infra_offline" | "intake" | "workflow_failure",
"severity": "info" | "warning" | "high" | "critical",
"title": "Short description",
"body": "Detailed message",
"link": "/security",
"timestamp": "2026-03-17T10:30:00Z",
"metadata": {}
}const ARKON_URL = "https://your-arkon-url";
const TOKEN = "default:your-agent-token";
async function sendEvent(eventType, content, metadata = {}) {
const res = await fetch(`${ARKON_URL}/api/ingest`, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
event_type: eventType,
content,
metadata,
}),
});
return res.json();
}
// Usage
await sendEvent("message_sent", "Hello from my agent!", {
model: "claude-sonnet-4-6",
tokens: 150,
});import requests
ARKON_URL = "https://your-arkon-url"
TOKEN = "default:your-agent-token"
def send_event(event_type: str, content: str, metadata: dict = None):
return requests.post(
f"{ARKON_URL}/api/ingest",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={
"event_type": event_type,
"content": content,
"metadata": metadata or {},
},
).json()
# Usage
send_event("message_sent", "Hello from my agent!", {
"model": "claude-sonnet-4-6",
"tokens": 150,
})Add to your openclaw.json:
{
"hooks": {
"ingest_url": "https://your-arkon-url/api/ingest",
"ingest_token": "default:your-agent-token"
}
}