Skip to content

Integration

This page covers what you need to build on the API: authentication, API keys and scopes, roles, webhooks, idempotent run creation, steering a live or stopped run, and pagination. The full endpoint list is in the API Reference; agent-to-agent integration is in Protocols and Ledger.

Authentication

Credential How to get it Use
Access token POST /api/v1/auth/login (or /register) Authorization: Bearer <token>; short-lived JWT (ARGUS_ACCESS_TOKEN_TTL_MINUTES)
Refresh token Returned with the access token POST /api/v1/auth/refresh; single-use and rotated on every refresh
API key Settings, API keys or POST /api/v1/auth/api-keys Authorization: Bearer argus_...; shown once at creation
Stream ticket POST /api/v1/runs/{id}/stream-ticket ?ticket= on the SSE stream, which cannot carry headers

Creating or revoking keys and changing the password need a signed-in session, never a key.

API keys and scopes

Every key can read. Writes need a scope:

Scope Allows
runs:write Start, steer, pause, cancel and delete runs; templates; protocol calls that change runs
councils:write Create and change councils and seats
providers:write Add, change, delete and test providers
skills:write Create, import, install, update, restore and delete skills
connections:write MCP servers and remote agents
webhooks:write Webhooks
knowledge:write Knowledge bases, documents and memory
* All of the above

A key with no scopes (or read) is read-only.

Roles

Role Can do
admin Everything a member can, plus user management, data retention, and ?all=true on the audit log
member Create and change their own councils, runs, skills, providers, connections, knowledge, webhooks and keys
viewer Read only. Every state-changing route and protocol write returns 403, whatever the key's scopes, and viewers can only create keys with scopes: ["read"]

Admins manage accounts with GET /api/v1/admin/users (role, active flag, last sign-in, run count) and PATCH /api/v1/admin/users/{id} (role, is_active). An admin cannot demote or deactivate themselves, and the last active admin cannot be demoted or deactivated (409). GET /api/v1/auth/me returns the caller's role.

Webhooks

Register an HTTPS endpoint with POST /api/v1/webhooks (url, events) to be notified of run.started, run.completed, run.failed, run.halted, run.cancelled and approval.requested (GET /api/v1/webhooks/events lists them). The signing secret is shown once at creation; rotate it with POST /webhooks/{id}/rotate-secret and send a test with POST /webhooks/{id}/test.

X-Argus-Event: run.completed
X-Argus-Delivery: <id, stable across retries>
X-Argus-Signature: t=<unix ts>,v1=<hex HMAC-SHA256(secret, "<ts>.<raw body>")>
import hashlib, hmac, time

def verify(secret: str, body: bytes, header: str, tolerance_s: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    ts = int(parts["t"])
    if abs(time.time() - ts) > tolerance_s:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Verify the signature over the raw body and reject old timestamps. Failed deliveries are retried after 1 s, 5 s and 30 s; an endpoint that fails 20 times in a row is disabled. GET /webhooks/{id}/deliveries shows the recent attempts. Private and loopback addresses are refused.

sequenceDiagram
    participant R as Run
    participant D as Dispatcher
    participant E as Your endpoint
    R->>D: run.completed
    D->>E: POST (signed)
    alt 2xx
        E-->>D: ok, failure count reset
    else error or timeout
        D->>E: retry after 1 s, 5 s, 30 s
        Note over D,E: 20 failed deliveries in a row disable the webhook
    end

Idempotent run creation

Send Idempotency-Key: <unique string> with POST /api/v1/runs to make retries safe. A repeat with the same key and body within 24 hours returns the original response with Idempotent-Replayed: true. The same key with a different body, or while the first request is still in flight, returns 409.

Steering a run

These routes need the runs:write scope. All but /continue act on a live run: if the run is not running or paused in this API process, they return 409.

Route Body Returns
POST /runs/{id}/continue optional {"guardrails": {...}}, merged over the old run's 201 and the new run. 409 unless the run is halted, failed or cancelled; 400 for a sub-run
POST /runs/{id}/budget any of add_usd, add_tokens (raise the limit now) and buffer_usd, buffer_tokens (set the reserve) 202 and the budget snapshot: used, limits, buffer
POST /runs/{id}/auto-mode tools and/or extensions (booleans; one left out keeps its value) 202 and {"tools": ..., "extensions": ...}
POST /runs/{id}/a2a the params of A2A message/send: {"message": {...}} 202 and the recorded A2A message

/continue resumes a stopped run where it stopped, as a new run whose resumed_from_id is the old run. The work the old run finished is replayed without model calls (see Resuming a stopped run). It accepts Idempotency-Key, like run creation.

curl -X POST "$ARGUS/api/v1/runs/$RUN/continue" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{"guardrails": {"budget": {"usd": 5}}}'

/budget adds to the budget or token cap only if the run has one. The reserve is drawn once, without asking, when the run reaches that limit, instead of halting.

curl -X POST "$ARGUS/api/v1/runs/$RUN/budget" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{"add_usd": 2, "buffer_usd": 1}'

/auto-mode switches auto mode. tools approves every request except limit raises, and extensions approves limit raises. Turning one on also answers the requests already waiting. A change to tools also reaches the run's running sub-councils.

curl -X POST "$ARGUS/api/v1/runs/$RUN/auto-mode" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{"tools": true}'

/a2a sends the council a message in A2A form: one to 20 text parts, an optional messageId, and metadata.to naming one member by name or role. Leave out to, or use council, to address everyone. A name that matches no member, or more than one, returns 404. The message reaches the addressed members at their next turn and stays in their instructions for the rest of the run. It is ledgered as a2a (direction inbound), and members answer with reply_to_user.

curl -X POST "$ARGUS/api/v1/runs/$RUN/a2a" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": {"parts": [{"kind": "text", "text": "Cite primary sources only."}], "metadata": {"to": "researcher"}}}'

Pagination

GET /api/v1/runs returns runs newest first; pass the last run's created_at as ?before= for the next page. GET /api/v1/audit uses ?before_id=. Each run in the list includes pending_approvals (approval requests waiting on a live run in this API process) and resumed_from_id (the run it resumed, or null).

Errors

Errors are JSON of the form {"error": {"code": ..., "message": ..., "details": ...}}: a stable code, a human-readable message and, where useful, details (for example the failing fields of an invalid guardrail layer, or the missing variables of a template). Rate-limited requests get 429.