Skip to content

HTTP API

export WARDRIK_URL=http://127.0.0.1:4747
curl $WARDRIK_URL/v1/agents -H "Authorization: Bearer $WARDRIK_TOKEN"
  • The daemon listens on 127.0.0.1:4747. Set http in config.yaml to change it.
  • Every request needs Authorization: Bearer <token>. Create one with wardrik token create. Webhooks and chat apps send none.
  • Bodies are JSON, up to 8 MB. Webhook and chat app routes accept bodies in any format.
  • Every response has a request-id header, echoing yours if you sent one.
  • GET /v1/openapi.json returns the OpenAPI 3.1 document for the library's routes. The daemon's own routes (/v1/owners/..., /v1/connections, /v1/tokens) are in wardrik_daemon's priv/openapi.json.
  • See Use the HTTP API for a walk-through.
{"error": {"type": "not_found", "message": "No agent runs under agt_01JF8X5RQ2."}}
type Status When
invalid_request 400 malformed or invalid input
unauthorized 401 missing, unknown, revoked or expired token
forbidden 403 the token isn't allowed to do this
not_found 404 doesn't exist, or the token can't access it
conflict 409 conflicts with current state: no such pending call, agent busy, or defined by a file
internal 500 a server bug
not_supported 501 not supported yet
unavailable 503 temporarily unavailable, such as the store; retry later
  • {agent} is a daemon-generated agent ID: agt_01JF8X5RQ2. URL-encode it as one segment.
  • {owner} is one URL-encoded segment: acme (an org), acme%2F%40jon (a user), or deployment.
  • ?agents= takes agent IDs, one per agents=. If omitted, it means every agent the token can access.

An agent has many conversations. To target one, append /conversations/{conversation} to the agent path:

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/conversations/C1/messages \
-H "Authorization: Bearer $WARDRIK_TOKEN" --json '{"content": "Hi"}'

These routes support the conversation path: read, clear (DELETE .../conversations/{conversation}), messages, decisions, approve, deny, authorization, cancel, stop, events, timeline, runs, calls, stop a call, and move.

  • Clearing a conversation deletes its history. The conversation ID still accepts messages.
  • In openapi.json, a conversation route has no operationId. Its x-wardrik-operation names the operation it serves, such as agent.ask.

GET /v1/agents

Lists the agents the token can access.

Parameter Type Description
agents string, repeated agent IDs to list
curl $WARDRIK_URL/v1/agents -H "Authorization: Bearer $WARDRIK_TOKEN"
{"agents": [{"id": "agt_01JF8X5RQ2", "status": "parked", "pending": 0, "node": "wardrik@box1"}]}

Each agent has id, conversation, status, pending, node, next_run and spent_today, as Read an agent describes them.

GET /v1/agents/{agent}

Returns the agent's current status and activity.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2 -H "Authorization: Bearer $WARDRIK_TOKEN"
{
"agent": {"id": "agt_01JF8X5RQ2"},
"status": "parked",
"pending": 0,
"activity": {
"doing": [{"type": "wardrik.run.interrupted",
"interrupts": [{"id": "toolu_01", "reason": "tool_approval", "message": "Open an issue?", "tool_call_id": "toolu_01"}]}],
"since": "2026-10-22T09:00:00.000000Z",
"pending": 0
},
"interrupts": [{"id": "toolu_01", "reason": "tool_approval", "message": "Open an issue?", "tool_call_id": "toolu_01"}],
"cursor": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"
}
Field Type Description
status string idle, running, parked (pending approval) or asleep
node string or null the node it runs on; null while asleep
pending integer messages queued behind the current one
activity object what it's doing, as activity
interrupts array calls pending approval
cursor string where its event log stands; pass it as after
next_run string or null when its next clock trigger runs
spent_today object what it spent today

PUT /v1/agents/{agent}

Starts the agent with the definition, or updates a running agent from its next turn.

The body is an agent definition. The daemon only accepts IDs it generated, so create the agent with POST /v1/owners/{owner}/agents first.

curl -X PUT $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2 -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"instructions": "You watch the incident queue.", "model": "anthropic:claude-sonnet-5", "tools": ["web_search"]}'

Returns the agent, as Read an agent does. An unsupported key returns 501.

GET /v1/agents/{agent}/definition

Returns the current definition, and lists its tools that aren't available yet.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/definition -H "Authorization: Bearer $WARDRIK_TOKEN"
{"definition": {"instructions": "Answer customers' questions about their orders.", "tools": ["crm/*"]},
"missing": ["crm/*"]}
Field Type Description
definition object the definition, as sent
missing array tools named that aren't there yet, like an MCP server not added
next_runs object when each trigger runs next, by name; null for a webhook

POST /v1/agents/{agent}/spawn

Starts the agent.

curl -X POST $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/spawn -H "Authorization: Bearer $WARDRIK_TOKEN"
{"agent": {"id": "agt_01JF8X5RQ2", "status": "idle", "pending": 0}}

POST /v1/agents/{agent}/stop

Stops the agent's process. The conversation is kept. The next message starts it again.

curl -X POST $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/stop -H "Authorization: Bearer $WARDRIK_TOKEN"
{"agent": {"id": "agt_01JF8X5RQ2", "status": "asleep", "pending": 0}}

DELETE /v1/agents/{agent}/conversation

Clears the agent's history. The agent, its definition and its other conversations are kept. Returns 409 while a turn is running or pending approval.

curl -X DELETE $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/conversation -H "Authorization: Bearer $WARDRIK_TOKEN"

Returns the agent, as Read an agent does.

DELETE /v1/agents/{agent}

Stops the agent and deletes its conversation, definition and triggers. Returns 204.

curl -X DELETE $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2 -H "Authorization: Bearer $WARDRIK_TOKEN"

DELETE /v1/agents

Removes each agent in ?agents=, or every agent the token can access.

Parameter Type Description
agents string, repeated agent IDs to forget
curl -X DELETE "$WARDRIK_URL/v1/agents?agents=agt_01JF8X5RQ2" -H "Authorization: Bearer $WARDRIK_TOKEN"
{"forgotten": ["agt_01JF8X5RQ2"], "kept": [], "failed": []}

kept and failed entries are {"id": ..., "why": ...}. An agent an agent file declares is kept.

POST /v1/agents/{agent}/move

Restarts the agent on another node. A running turn ends. Send the message again after the move.

Field Type Description
node string, required the node's name
curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/move -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"node": "wardrik@box2"}'
{"agent": {"id": "agt_01JF8X5RQ2", "status": "idle", "pending": 0, "node": "wardrik@box2"}}

POST /v1/agents/{agent}/messages

Queues a message for the agent. Returns 202.

Field Type Description
content string the text
parts array the text as parts, in place of content
id string your ID for it; a message sent again with the same id is taken once
curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/messages -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"id": "msg_01", "content": "What is on fire?"}'
{"message": {"id": "msg_01", "cursor": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"}}

Read the reply from the events after cursor.

POST /v1/agents/{agent}/cancel

Ends the current turn and drops queued messages. The agent keeps running. Returns 202.

curl -X POST $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/cancel -H "Authorization: Bearer $WARDRIK_TOKEN"

POST /v1/agents/cancel

Ends the current turn of each agent in ?agents=, or every agent the token can access. Returns 202.

curl -X POST "$WARDRIK_URL/v1/agents/cancel?agents=agt_01JF8X5RQ2" -H "Authorization: Bearer $WARDRIK_TOKEN"
{"cancelled": ["agt_01JF8X5RQ2"]}

GET /v1/agents/{agent}/calls

Lists the agent's running tool calls. Returns 404 while its process is stopped.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/calls -H "Authorization: Bearer $WARDRIK_TOKEN"
{"calls": [{"id": "toolu_01", "name": "github__search_issues", "elapsed_ms": 1250}]}

DELETE /v1/agents/{agent}/calls/{call}

Stops one tool call. The model receives an error and the turn continues. Returns 204.

curl -X DELETE $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/calls/toolu_01 -H "Authorization: Bearer $WARDRIK_TOKEN"

GET /v1/interrupts

Lists calls pending approval.

Parameter Type Description
agents string, repeated agent IDs to cover
curl $WARDRIK_URL/v1/interrupts -H "Authorization: Bearer $WARDRIK_TOKEN"
{"interrupts": [{"agent": {"id": "agt_01JF8X5RQ2"},
"interrupt": {"id": "toolu_01", "reason": "tool_approval", "message": "Open an issue?", "tool_call_id": "toolu_01"}}]}

An entry has conversation when the call is in a conversation.

POST /v1/agents/{agent}/interrupts/{interrupt}/approve

Approves one call. It runs with the model's arguments.

Field Type Description
note string text the model receives with the call's result
curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/interrupts/toolu_01/approve \
-H "Authorization: Bearer $WARDRIK_TOKEN" --json '{"note": "Only staging."}'
{"decisions": [{"id": "toolu_01", "decision": "approved"}]}

POST /v1/agents/{agent}/interrupts/{interrupt}/deny

Denies one call.

Field Type Description
reason string text the model receives instead of the call's result
curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/interrupts/toolu_01/deny \
-H "Authorization: Bearer $WARDRIK_TOKEN" --json '{"reason": "Not this quarter."}'
{"decisions": [{"id": "toolu_01", "decision": "rejected"}]}

POST /v1/agents/{agent}/decisions

Approves or denies several pending calls at once.

Field Type Description
decisions[].id string, required the waiting call's ID
decisions[].decision string, required approve or reject
decisions[].note string for an approval
decisions[].reason string for a rejection
curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/decisions -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"decisions": [{"id": "toolu_01", "decision": "reject", "reason": "Not this quarter."},
{"id": "toolu_02", "decision": "approve"}]}'
{"decisions": [{"id": "toolu_01", "decision": "rejected"}, {"id": "toolu_02", "decision": "approved"}]}

GET /v1/agents/{agent}/interrupts/{interrupt}/authorization

Returns the sign-in URL for a call pending with reason authorization.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/interrupts/toolu_01/authorization \
-H "Authorization: Bearer $WARDRIK_TOKEN"
{"url": "https://github.com/login/device", "code": "WDJB-MJHT"}

code is there only for a device sign-in.

GET /v1/events

Returns agents' events, as a JSON page or a server-sent event stream.

Parameter Type Description
agents string, repeated agent IDs to read
types string, repeated event types, like wardrik.run.completed; all unless set
after string the cursor to read after: a page's next, a streamed event's id, or a snapshot's cursor
limit integer events per page; 100 unless set
curl "$WARDRIK_URL/v1/events?agents=agt_01JF8X5RQ2&types=wardrik.run.completed" \
-H "Authorization: Bearer $WARDRIK_TOKEN"
{"events": [], "next": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"}

Stream with Accept: text/event-stream:

curl -N "$WARDRIK_URL/v1/events" -H "Accept: text/event-stream" -H "Authorization: Bearer $WARDRIK_TOKEN"
id: W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDJdXQ
data: {"specversion":"1.0","type":"wardrik.run.completed","agent":"agt_01JF8X5RQ2",...}
  • Each event's id is a cursor. To resume, reconnect with Last-Event-ID or ?after=.
  • Without a cursor, a page starts at the oldest event, and a stream starts at the next new event.
  • Deltas have no id.
  • An idle stream sends a comment every 15 seconds.
  • If the log was trimmed past your cursor, you receive wardrik.events.dropped, regardless of types.

GET /v1/agents/{agent}/events reads one agent's log the same way.

GET /v1/events/head

Returns the current end-of-log cursor, to read only new events.

curl $WARDRIK_URL/v1/events/head -H "Authorization: Bearer $WARDRIK_TOKEN"
{"cursor": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"}

GET /v1/agents/{agent}/timeline

Returns the conversation in readable form, oldest first.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/timeline -H "Authorization: Bearer $WARDRIK_TOKEN"
{
"items": [
{"id": "msg_01", "kind": "user", "text": "What is on fire?", "sender": "acme/@ana"},
{"id": "run_01", "kind": "run", "status": "completed",
"steps": [{"id": "s1", "type": "text", "text": "Nothing right now.", "live": false}]}
],
"cursor": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"
}

A run's steps are thinking, text or tool (with name, arguments, status, result).

GET /v1/agents/{agent}/runs

Returns each turn, newest first, with its cost, and totals.

curl $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/runs -H "Authorization: Bearer $WARDRIK_TOKEN"
{
"runs": [{"id": "run_01", "status": "completed", "started_at": "2026-10-22T09:00:00Z",
"finished_at": "2026-10-22T09:00:04Z", "duration_ms": 4120, "model": "anthropic:claude-sonnet-5",
"tool_calls": 2, "tool_errors": 0, "input_tokens": 1830, "output_tokens": 212, "cost_micro_usd": 8670}],
"totals": {"runs": 1, "failed": 0, "tool_calls": 2, "input_tokens": 1830, "output_tokens": 212,
"cost_micro_usd": 8670, "last_at": "2026-10-22T09:00:04Z"},
"cursor": "W1siYWd0XzAxSkY4WDVSUTIiLG51bGwsNDFdXQ"
}

PUT /v1/agents/{agent}/triggers/{trigger}

Sets or changes one trigger. Returns 404 if the agent has no definition.

The body has the keys of a trigger: every, timezone, prompt, prompt_file, overlap, missed, jitter, feed, webhook.

curl -X PUT $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/triggers/sweep -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"every": "*/30 * * * *", "prompt": "Check the queue.", "overlap": "skip"}'
{"every": "*/30 * * * *", "prompt": "Check the queue.", "overlap": "skip"}

If every and timezone are unchanged, the trigger keeps its next run time.

DELETE /v1/agents/{agent}/triggers/{trigger}

Deletes the trigger. Returns its last state.

curl -X DELETE $WARDRIK_URL/v1/agents/agt_01JF8X5RQ2/triggers/sweep -H "Authorization: Bearer $WARDRIK_TOKEN"
{"every": "*/30 * * * *", "prompt": "Check the queue.", "overlap": "skip"}

POST /v1/hooks/{agent}/{trigger}

Sends a webhook request to the agent's webhook trigger. Returns 202.

  • No token. The request authenticates with the trigger's secret, as Authorization: Bearer or a Standard Webhooks signature.
  • The body can be any content type. Wardrik passes the body and headers to the agent as sent.
  • A repeated request sends one message.
  • 404 if the trigger doesn't exist or the secret doesn't match. 503 means retry later.
curl $WARDRIK_URL/v1/hooks/agt_01JF8X5RQ2/issues \
-H "Authorization: Bearer s3cret" --json '{"action": "opened"}'

POST /v1/hooks/{agent}/{trigger}/{secret} takes the secret as the last path segment, for services that only accept a URL. Treat that URL as a secret.

POST /v1/channels/{channel}/{path}

Routes a chat app's request, such as a Slack event, to the named channel in config.yaml.

  • No token. The channel verifies the request's signature.
  • The body can be any content type.
  • The response is the channel's status, headers and body, in the chat app's format.
  • 404 if no channel with that name accepts requests.
curl $WARDRIK_URL/v1/channels/slack/events \
-H "X-Slack-Signature: v0=a2114d57..." -H "X-Slack-Request-Timestamp: 1531420618" \
--json '{"type": "url_verification", "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}'
3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P

See Slack.

GET /v1/deployment/nodes

Lists the nodes, with the running and stopped agent counts on each.

curl $WARDRIK_URL/v1/deployment/nodes -H "Authorization: Bearer $WARDRIK_TOKEN"
{"nodes": [{"name": "wardrik@box1", "agents": 12}, {"name": "wardrik@box2", "agents": 9}], "asleep": 40}

POST /v1/deployment/reload

Rereads every agent's definition, or those in ?agents=. Each applies from the agent's next turn.

curl -X POST $WARDRIK_URL/v1/deployment/reload -H "Authorization: Bearer $WARDRIK_TOKEN"
{"reloaded": ["wardrik@box1"], "problems": ["agents/broken.md: There's no tool nope here."]}

GET /v1/deployment/audit

Returns a page of the audit log, oldest first.

Parameter Type Description
starting_after integer the sequence to read after, a page's next
limit integer changes per page; 100 unless set
curl "$WARDRIK_URL/v1/deployment/audit?starting_after=11" -H "Authorization: Bearer $WARDRIK_TOKEN"
{"events": [{"specversion": "1.0", "type": "wardrik.agent.defined", "...": "..."}], "next": 12}

Each entry is a CloudEvent, like an agent's events.

POST /v1/owners/{owner}/agents

Generates an agent ID, stores the record, and defines the agent. Returns 201.

Field Type Description
name string, required unique in the org: letters, digits, _, ., -
any definition key the agent's definition
curl $WARDRIK_URL/v1/owners/acme%2F%40jon/agents -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"name": "notes", "model": "anthropic:claude-haiku-4-5", "instructions": "You keep Jon'\''s notes."}'
{"id": "agt_01JF8X5RQ2M3V9ZK0B7Y4T6WHN", "name": "notes", "org": "acme", "owner": "acme/@jon"}

workspace.shared names agents of the org by name. A name in use is a 409.

GET /v1/owners/{owner}/agents

Lists the agents in the owner's org that the token can read.

Parameter Type Description
name string the agent's name; every agent unless set
curl "$WARDRIK_URL/v1/owners/acme/agents?name=notes" -H "Authorization: Bearer $WARDRIK_TOKEN"
{"agents": [{"id": "agt_01JF8X5RQ2M3V9ZK0B7Y4T6WHN", "name": "notes", "org": "acme", "owner": "acme/@jon"}]}

GET /v1/owners/{owner}/secrets

Lists the owner's secret names and purposes, never values.

curl $WARDRIK_URL/v1/owners/acme/secrets -H "Authorization: Bearer $WARDRIK_TOKEN"
{"secrets": [{"name": "ANTHROPIC_API_KEY", "purpose": "api_key"}, {"name": "linear", "purpose": "grant"}]}

purpose is api_key, client_secret, header, signing_secret, grant (a connected account), token (a chat app install) or secret.

PUT /v1/owners/{owner}/secrets/{name}

Stores an encrypted value under the name, replacing any existing one. Returns 204.

Field Type Description
value string, required the secret
purpose string, required api_key, client_secret, header or signing_secret; it's only read for that
curl -X PUT $WARDRIK_URL/v1/owners/acme/secrets/ANTHROPIC_API_KEY -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"value": "sk-ant-0123456789abcdef", "purpose": "api_key"}'

${NAME} in config.yaml resolves the deployment owner's secrets.

DELETE /v1/owners/{owner}/secrets/{name}

Removes the secret. Returns 204, even if it didn't exist.

curl -X DELETE $WARDRIK_URL/v1/owners/acme/secrets/ANTHROPIC_API_KEY -H "Authorization: Bearer $WARDRIK_TOKEN"

GET /v1/owners/{owner}/ceilings

Lists the org's spending ceilings, with its agents' spend this period.

curl $WARDRIK_URL/v1/owners/acme/ceilings -H "Authorization: Bearer $WARDRIK_TOKEN"
{"ceilings": [{"ceiling": "plan", "per": "month", "on_exhausted": "ask", "limit": {"usd": 20.0},
"spent": {"usd": 12.4, "tokens": 81200}, "granted": {}, "starts_over": "2026-11-01"}]}

GET /v1/owners/{owner}/servers

Lists the MCP servers available to the owner's agents: the owner's, then the org's, then the deployment's.

curl $WARDRIK_URL/v1/owners/acme/servers -H "Authorization: Bearer $WARDRIK_TOKEN"
{"servers": [{"owner": "acme", "name": "crm", "source": "runtime", "url": "https://mcp.crm.example/mcp", "auth": "secret"},
{"owner": "deployment", "name": "github", "source": "config", "url": "https://api.githubcopilot.com/mcp/", "auth": "oauth"}]}

POST /v1/owners/{owner}/servers

Adds an MCP server for the owner's agents. Its tools are available from their next turn. Returns 201.

Field Type Description
name string, required letters, digits, -, _, up to 32, never __; agents name its tools name/*
url string, required an https Streamable HTTP URL
auth object, required {"none": {}}, {"secret": {"name": ..., "header": ..., "scheme": ...}}, or {"oauth": {...}}
only array the server's tool names to take
except array the server's tool names to leave

oauth takes scopes, and provider (an OAuth app's name) or issuer, client_id and client_secret. If empty, the daemon discovers the server's OAuth metadata.

curl $WARDRIK_URL/v1/owners/acme/servers -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"name": "crm", "url": "https://mcp.crm.example/mcp", "auth": {"oauth": {}}}'
{"server": "crm", "connected": false, "authorization": {"url": "https://auth.crm.example/authorize?client_id=…&state=…"}}

DELETE /v1/owners/{owner}/servers/{name}

Removes one of the owner's servers, and deletes its sign-ins.

curl -X DELETE $WARDRIK_URL/v1/owners/acme/servers/crm -H "Authorization: Bearer $WARDRIK_TOKEN"
{"owner": "acme", "name": "crm", "source": "runtime", "url": "https://mcp.crm.example/mcp", "auth": "secret"}

GET /v1/owners/{owner}/notify_targets

Lists the notice targets available to the owner's agents: the owner's, then the org's, then the deployment's.

curl $WARDRIK_URL/v1/owners/acme/notify_targets -H "Authorization: Bearer $WARDRIK_TOKEN"
{"targets": [{"owner": "acme", "name": "ops", "source": "runtime", "kind": "webhook",
"url": "https://hooks.acme.example/wardrik", "secret": {"name": "OPS_HOOK_SECRET"}}]}

POST /v1/owners/{owner}/notify_targets

Adds a notice webhook. Returns 201.

Field Type Description
name string, required what definitions name in notify; letters, digits, -, _, up to 32
url string, required an https URL; redirects aren't followed
secret.name string a vault secret that signs each notice
curl $WARDRIK_URL/v1/owners/acme/notify_targets -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"name": "ops", "url": "https://hooks.acme.example/wardrik", "secret": {"name": "OPS_HOOK_SECRET"}}'
{"owner": "acme", "name": "ops", "source": "runtime", "kind": "webhook",
"url": "https://hooks.acme.example/wardrik", "secret": {"name": "OPS_HOOK_SECRET"}}

DELETE /v1/owners/{owner}/notify_targets/{name}

Removes one of the owner's targets. Returns its last state.

curl -X DELETE $WARDRIK_URL/v1/owners/acme/notify_targets/ops -H "Authorization: Bearer $WARDRIK_TOKEN"

GET /v1/owners/{owner}/providers

Lists the owner's OAuth apps, never client secrets.

curl $WARDRIK_URL/v1/owners/acme/providers -H "Authorization: Bearer $WARDRIK_TOKEN"
{"providers": [{"owner": "deployment", "name": "google", "source": "runtime", "issuer": "https://accounts.google.com",
"client_id": "868288504182-example.apps.googleusercontent.com", "client_secret": {"name": "GOOGLE_CLIENT_SECRET"},
"scopes": ["https://www.googleapis.com/auth/adwords"], "client_auth": "post", "flow": "browser"}]}

POST /v1/owners/{owner}/providers

Adds an OAuth app for the owner's users. Returns 201.

Field Type Description
name string, required the account it grants; letters, digits, -, _, up to 32
issuer string the issuer URL; its metadata names the endpoints
resource string the API its tokens are for; finds the issuer if none is given
authorization_endpoint, token_endpoint string for a service without metadata
client_id string the app's client ID
client_secret.name string a vault secret stored as client_secret
client_auth string post (default) or basic
scopes array scopes to ask for
flow string browser (default) or device
authorization_params object extra browser sign-in params, like access_type

It requires issuer, resource, or both endpoints.

curl $WARDRIK_URL/v1/owners/acme/providers -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"name": "x", "authorization_endpoint": "https://x.com/i/oauth2/authorize",
"token_endpoint": "https://api.x.com/2/oauth2/token", "client_id": "cnh3-example",
"client_secret": {"name": "X_CLIENT_SECRET"}, "client_auth": "basic",
"scopes": ["tweet.read", "tweet.write", "offline.access"]}'

Returns the stored app, in the format of List OAuth apps.

DELETE /v1/owners/{owner}/providers/{name}

Removes one of the owner's apps. Returns its last state.

curl -X DELETE $WARDRIK_URL/v1/owners/acme/providers/x -H "Authorization: Bearer $WARDRIK_TOKEN"

The token user's connected accounts. Any token can manage its own.

GET /v1/connections

Lists the available providers, and whether each is connected.

curl $WARDRIK_URL/v1/connections -H "Authorization: Bearer $WARDRIK_TOKEN"
{"connections": [{"provider": "github", "connected": true, "signing_in": false},
{"provider": "linear", "connected": false, "signing_in": true}]}
Field Type Description
provider string an OAuth app's name, or an MCP server's with its own sign-in
connected boolean whether it's connected
signing_in boolean whether a sign-in you started is still under way

POST /v1/connections/{provider}

Starts a sign-in, or returns connected: true if already connected.

curl -X POST $WARDRIK_URL/v1/connections/github -H "Authorization: Bearer $WARDRIK_TOKEN"
{"provider": "github", "connected": false, "authorization": {"url": "https://github.com/login/device", "code": "WDJB-MJHT"}}

Open authorization.url. For a device sign-in, enter code there.

POST /v1/connections/{provider}/pair

Completes a browser sign-in with the code from its page. Five wrong codes cancel the sign-in.

Field Type Description
code string, required the code, as BCDF-GHJK
curl $WARDRIK_URL/v1/connections/linear/pair -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"code": "BCDF-GHJK"}'
{"provider": "linear", "connected": true, "signing_in": false}

DELETE /v1/connections/{provider}

Forgets your account. The next call that needs it asks you to sign in again. Returns 204, or 404 if there is no such connection.

curl -X DELETE $WARDRIK_URL/v1/connections/github -H "Authorization: Bearer $WARDRIK_TOKEN"

GET /v1/tokens

Lists every token, never secrets.

curl $WARDRIK_URL/v1/tokens -H "Authorization: Bearer $WARDRIK_TOKEN"
{"tokens": [{"id": "mzxw6ytboi", "name": "ana's laptop", "subject": "user:acme/@ana",
"groups": ["payments-eng"], "expires": "2026-12-01T00:00:00Z"}]}

POST /v1/tokens

Creates a token that authenticates as subject. Returns 201 with the secret, shown once.

Field Type Description
name string, required what it's for
subject string, required a person, as user:acme/@ana, or agent:ID for an agent's own
groups array the user's groups, which bindings can name
expires_in integer seconds, from 60 to a year; 30 days unless set
curl $WARDRIK_URL/v1/tokens -H "Authorization: Bearer $WARDRIK_TOKEN" \
--json '{"name": "ana laptop", "subject": "user:acme/@ana", "groups": ["payments-eng"], "expires_in": 2592000}'
{"id": "mzxw6ytboi", "name": "ana laptop", "subject": "user:acme/@ana", "groups": ["payments-eng"],
"expires": "2026-12-01T00:00:00Z", "secret": "wdk_mzxw6ytboi_0123456789abcdef"}

Only the admin user can create a user:admin token.

DELETE /v1/tokens/{id}

Revokes the token immediately. Returns 204.

curl -X DELETE $WARDRIK_URL/v1/tokens/mzxw6ytboi -H "Authorization: Bearer $WARDRIK_TOKEN"

GET /v1/workers is a WebSocket for an MCP server that dials in. See Tools in your app.

  • Messages are JSON-RPC 2.0, one per text frame, as MCP 2025-06-18.
  • Wardrik is the client. It sends initialize, tools/list, tools/call and notifications/cancelled.
  • A call's _meta has the calling agent and an idempotencyKey. Return _meta.costUsd to report cost.
  • Agents with workers/* in tools see the worker's tools as workers__NAME.
  • A non-WebSocket request with a valid token returns 426. The socket closes with 1008 when the token is revoked or expires.