Skip to content

Webhooks

Cloud Only

Webhooks are available in the Cloud version only.

Webhooks let ADHDev Cloud push machine and agent events to your own HTTP endpoint.

Important current behavior:

  • the webhook API is live
  • the dedicated /webhooks dashboard page is not currently a stable standard navigation surface
  • use the REST API reference as the canonical contract for payloads, events, and delivery-history shapes
  • webhook create / toggle / delete / test actions are recent-login protected cloud account operations and require a fresh dashboard session JWT, not an API key

Creating a Webhook

Create the webhook from a currently signed-in cloud dashboard session. The underlying request body is:

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

If you call the mutating webhook endpoints from a stale browser session or with an API key, the server returns 403 RECENT_LOGIN_REQUIRED instead of provisioning the hook.

The create response returns:

  • the webhook record
  • a secret shown once for signature verification

Use ["*"] in events to subscribe to every supported event.

Events

EventTrigger
agent:generating_startedAgent started generating a response
agent:generating_completedAgent finished generating
agent:waiting_approvalAgent is waiting for approval
agent:errorAgent encountered an error
webhook:testTest delivery requested explicitly

Payload Format

json
{
  "event": "agent:generating_completed",
  "payload": {
    "chatTitle": "Claude Code · myproject",
    "ideType": "claude-code",
    "duration": 42,
    "timestamp": 1714000000000
  },
  "timestamp": 1714000000000
}

Signature Verification

Each webhook request includes:

  • X-ADHDev-Signature
  • X-ADHDev-Event

The signature format is:

text
X-ADHDev-Signature: t=1714000000000,v1=a3f9c2b1...

Verify it against the raw request body.

js
import crypto from 'crypto'

function verifySignature(body, signature, secret) {
  const parts = Object.fromEntries(signature.split(',').map((p) => p.split('=')))
  const timestamp = parts.t
  const received = parts.v1
  const payload = `${timestamp}.${body}`
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(received),
    Buffer.from(expected)
  )
}

// Express example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-adhdev-signature']
  const body = req.body.toString('utf8')
  if (!verifySignature(body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }
  const event = JSON.parse(body)
  // handle event...
  res.sendStatus(200)
})
python
import hmac
import hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    parts = dict(p.split('=', 1) for p in signature.split(','))
    timestamp = parts.get('t', '')
    received = parts.get('v1', '')
    payload = f"{timestamp}.{body.decode('utf-8')}".encode()
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(received, expected)

# Flask example
@app.route('/webhook', methods=['POST'])
def webhook():
    sig = request.headers.get('X-ADHDev-Signature', '')
    if not verify_signature(request.data, sig, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    event = request.get_json()
    # handle event...
    return '', 200

Your webhook secret is shown once when you create the webhook — store it securely.

Management Endpoints

text
GET    /api/v1/webhooks
POST   /api/v1/webhooks
PATCH  /api/v1/webhooks/{webhookId}
DELETE /api/v1/webhooks/{webhookId}
GET    /api/v1/webhooks/{webhookId}/deliveries?limit=20
POST   /api/v1/webhooks/{webhookId}/test

GET endpoints are the safest automation surface. The mutating endpoints (POST, PATCH, DELETE, test) are recent-login protected dashboard-session operations.

Retry Policy

Failed deliveries are retried up to 3 times with exponential backoff.

Plan Limits

PlanMax Webhooks
Free2
Pro10
Team50
EnterpriseUnlimited

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