Skip to content

REST API

Cloud Only

The Cloud REST API is available at https://api.adhf.dev. Self-hosted users can access a local API — see Self-hosted API.

This page documents the hosted cloud automation surface.

It does not try to cover:

  • local standalone endpoints such as /api/v1/status
  • self-hosted runtime operator flows such as session-host recovery
  • local terminal mux endpoints such as /api/v1/mux/*

For those, use the OSS self-hosted docs instead.

Authentication

All API requests require an API key in the Authorization header:

bash
curl -H "Authorization: Bearer adk_..." \
     https://api.adhf.dev/api/v1/daemons

Create API keys from Dashboard → Settings → API Keys. Each key can be scoped to specific permissions.

For normal cloud automation, API keys are the main auth surface.

Some sensitive cloud-account mutations now require a recent browser login instead of API-key auth. Those routes expect a fresh dashboard JWT session and return 403 RECENT_LOGIN_REQUIRED when called with an API key or a stale session.

Current recent-login protected routes:

  • POST /api/v1/webhooks
  • PATCH /api/v1/webhooks/{webhookId}
  • DELETE /api/v1/webhooks/{webhookId}
  • POST /api/v1/webhooks/{webhookId}/test
  • POST /api/v1/daemons/{daemonId}/disconnect
  • POST /api/v1/daemons/{daemonId}/revoke

Scopes

ScopeDescription
ide:readList daemons, read IDE state
ide:controlLaunch/stop IDEs, send daemon commands
agent:readRead chat messages, agent status
agent:controlSend messages, approve/reject actions
terminal:execExecute terminal commands on machines
webhook:manageInspect deliveries and, with a recent dashboard login, manage webhooks

Public API Shape

For most cloud integrations, think in these layers:

  • GET /api/v1/daemons to find connected machines
  • GET /api/v1/daemons/{daemonId}/status to inspect machine and session state
  • /api/v1/shortcuts/* for the common agent actions you actually want
  • /api/v1/webhooks/* for event delivery to your own systems

Prefer Shortcuts unless you specifically need the raw daemon command router.

All daemon and shortcut routes are scoped to machines and sessions owned by the authenticated cloud account. Supplying some other account's daemon or synthetic session id returns 404 instead of crossing account boundaries.


Daemons

Manage connected machines (daemons) and their IDEs.

List Daemons

http
GET /api/v1/daemons

Scope: ide:read

Returns all connected machines with their managed IDEs, CLIs, and ACP agents.

Response:

json
{
  "daemons": [
    {
      "id": "c79baa8f...",
      "hostname": "M1-Server",
      "nickname": "작업용",
      "platform": "darwin",
      "cdpConnected": true,
      "ides": [
        { "id": "c79baa8f:ide:cursor_myproject", "type": "cursor", "cdpConnected": true }
      ],
      "clis": [
        { "id": "c79baa8f:cli:gemini-cli", "type": "gemini-cli", "name": "Gemini CLI" }
      ],
      "acps": [
        { "id": "c79baa8f:acp:claude-acp", "type": "claude-acp" }
      ]
    }
  ]
}

Get Daemon Status

http
GET /api/v1/daemons/{daemonId}/status

Scope: ide:read

Returns detailed daemon status including IDE/CLI state, workspace info, and agent activity.

Send Daemon Command

http
POST /api/v1/daemons/{daemonId}/command

Scope: ide:control

Send a direct command to the target machine.

For most integrations, prefer the Shortcuts API below. POST /daemons/:id/command is the lower-level escape hatch.

Body:

json
{
  "type": "send_chat",
  "payload": { "message": "Hello!" }
}

Available Command Types

CommandTargetPayloadDescription
send_chatIDE/CLImessageSend a chat message
read_chatIDE/CLIRead current chat contents
resolve_actionIDE/CLIactionApprove/reject agent action
screenshotIDEwidth?Take a screenshot
launch_ideDaemonideType, enableCdp?Launch an IDE
launch_cliDaemoncliType, dir?, model?Start CLI/ACP session
stop_cliDaemoncliTypeStop CLI session

Not every command in the internal router belongs in public automation material. If you are building a normal integration, stay on the documented command set or the shortcut endpoints.

Execute Terminal Command

http
POST /api/v1/daemons/{daemonId}/terminal

Scope: terminal:exec

Execute a terminal command on the daemon machine.

Body:

json
{
  "command": "ls -la",
  "name": "my-terminal",
  "cwd": "/home/user"
}

Disconnect Daemon

http
POST /api/v1/daemons/{daemonId}/disconnect

Scope: ide:control

Force disconnect the daemon. The daemon can reconnect automatically.

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.

Revoke Daemon Token

http
POST /api/v1/daemons/{daemonId}/revoke

Scope: ide:control

Revoke the daemon's connection token permanently. Requires running adhdev setup again on the machine.

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.


Shortcuts

Convenience endpoints for the most common agent actions.

Launch IDE / CLI / ACP

http
POST /api/v1/shortcuts/{daemonId}/launch

Scope: ide:control

Body:

json
{ "type": "cursor" }
json
{ "type": "gemini-cli", "dir": "/path/to/project" }
json
{ "type": "claude-acp", "dir": "/path", "model": "opus" }

Stop CLI / ACP

http
POST /api/v1/shortcuts/{daemonId}/stop

Scope: ide:control

Body:

json
{ "type": "gemini-cli" }

Send Chat Message

http
POST /api/v1/shortcuts/{ideId}/chat

Scope: agent:control

Send a message to an AI agent. The ideId is the machine-scoped target ID returned by the daemon/session status APIs, including synthetic session routes like {daemonId}:session:{sessionId}.

This is the default send path for external automation.

Body (legacy text form):

json
{ "message": "Fix the bug in auth.ts" }

Body (canonical envelope form):

json
{
  "input": {
    "parts": [
      { "type": "text", "text": "Fix the bug in auth.ts" }
    ],
    "textFallback": "Fix the bug in auth.ts"
  }
}

Optional — specify agent type for multi-agent IDEs:

json
{ "message": "Fix the bug", "agentType": "cursor" }

You must provide either message or input.

Read Chat

http
GET /api/v1/shortcuts/{ideId}/chat

Scope: agent:read

Read the current chat contents from an agent. Optionally filter by ?agentType=cursor.

Chat Debug Bundle

http
GET /api/v1/shortcuts/{ideId}/chat/debug
POST /api/v1/shortcuts/{ideId}/chat/debug

Scope: agent:read

Build a bounded, sanitized debug bundle for the current chat/session. The daemon generates the authoritative provider/parser/session/terminal evidence; POST may include a dashboard frontendSnapshot to supplement it with currently rendered frontend state.

Optional body for POST:

json
{ "agentType": "hermes", "frontendSnapshot": { "activeConversation": { "sessionId": "session_..." } } }

The response includes bundle and copy-ready text. Secrets and credentials are redacted by default.

Approve / Reject Action

http
POST /api/v1/shortcuts/{ideId}/approve

Scope: agent:control

Approve or reject a pending agent action.

Body:

json
{ "action": "approve" }

or

json
{ "action": "reject", "agentType": "cursor" }

Get Agent Status

http
GET /api/v1/shortcuts/{ideId}/status

Scope: agent:read

Returns current status (idle, generating, waiting_approval, error), provider summary metadata/controls when present, and workspace info.

Collaboration APIs

Collaboration features have their own API surface under /api/v1/orgs/*.

That includes:

  • creating or listing Rafts and Team Workspaces
  • inviting members
  • reading collaboration machine/session state
  • requesting or approving shared-session access

Invite acceptance is bound to the invited email address. If the signed-in cloud user does not match the invited email, the join request is rejected.

If you are not using collaboration features, you can ignore this part of the API entirely.


Webhooks

Manage webhook subscriptions for real-time event notifications. See Webhooks feature guide for setup instructions and signature verification.

List Webhooks

http
GET /api/v1/webhooks

Scope: webhook:manage

Create Webhook

http
POST /api/v1/webhooks

Scope: webhook:manage

Body:

json
{
  "url": "https://example.com/hook",
  "events": ["agent:generating_completed", "agent:waiting_approval"]
}

Use ["*"] to subscribe to all events. The response includes a secret (shown only once) for signature verification.

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.

Toggle Webhook

http
PATCH /api/v1/webhooks/{webhookId}

Scope: webhook:manage

Body:

json
{ "active": false }

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.

Delete Webhook

http
DELETE /api/v1/webhooks/{webhookId}

Scope: webhook:manage

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.

List Deliveries

http
GET /api/v1/webhooks/{webhookId}/deliveries?limit=20

Scope: webhook:manage

Returns recent delivery history with status codes, response bodies, and timing.

Test Webhook

http
POST /api/v1/webhooks/{webhookId}/test

Scope: webhook:manage

Sends a test webhook:test event to the webhook URL.

This is a recent-login protected cloud action. API keys and stale browser sessions receive 403 RECENT_LOGIN_REQUIRED.


Events

These events are delivered to webhooks and also drive live cloud notification flows.

EventDescription
agent:generating_startedAgent started generating a response
agent:generating_completedAgent finished generating (includes duration in seconds)
agent:waiting_approvalAgent is waiting for user approval
agent:errorAgent encountered an error
machine:connectedMachine came online
machine:disconnectedMachine went offline

Event Payload

json
{
  "event": "agent:generating_completed",
  "ideId": "c79baa8f:ide:cursor_myproject",
  "ideType": "cursor",
  "duration": 12.5,
  "timestamp": 1710000000000
}

Typical Flow

The most common API flow is:

  1. List machines with GET /api/v1/daemons
  2. Pick a target agent from the daemon status payload
  3. Send a message with POST /api/v1/shortcuts/{ideId}/chat
  4. Poll GET /api/v1/shortcuts/{ideId}/status or use webhooks
  5. Read the transcript with GET /api/v1/shortcuts/{ideId}/chat

What This Page Excludes

If you are looking for any of these, this is the wrong API page:

  • standalone GET /api/v1/status
  • standalone POST /api/v1/command
  • runtime snapshot/events endpoints for hosted local CLI sessions
  • terminal mux workspace endpoints

Those belong to Self-hosted API.


Rate Limits

Per-Request Limits

LimitValue
API Key120 requests / minute
IP address60 requests / minute
Auth endpoints10 requests / 5 minutes
Command timeout60 seconds

Monthly Call Limits

PlanMonthly API Calls
Free1,000
Pro50,000
Team500,000
EnterpriseUnlimited

Error Codes

StatusCodeDescription
400Bad request (validation failed)
401AUTH_REQUIREDMissing Authorization header
401AUTH_INVALIDInvalid or expired API key
403AUTH_FORBIDDENAPI key lacks required scope
403RECENT_LOGIN_REQUIREDSensitive cloud action requires a fresh dashboard login instead of API-key auth or a stale session
404Daemon/resource not found, expired invite/share, or target not owned by the authenticated account
429RATE_LIMITEDPer-minute rate limit exceeded
429API_LIMIT_EXCEEDEDMonthly API call limit reached
500Command send failed (daemon offline)
503Daemon connected but WebSocket disconnected
504Command response timeout (exceeded 60s)

Hosted cloud docs live here. Open-source and self-hosted docs live in the OSS repository.