Skip to content

Webhooks

Superficie congelada (UI del panel)

La página dedicada de webhooks en el panel de la nube está actualmente congelada por una decisión de producto explícita (2026-07-04, consulta docs/FROZEN_SURFACES.md en el repositorio): la entrada de la barra lateral está oculta y /webhooks redirige a /dashboard. La API de webhooks y el pipeline de entrega descritos a continuación siguen activos y se mantienen, pero no hay planeado trabajo de nuevas funciones de webhook hasta que se levante la congelación. Gestiona los webhooks a través de la superficie de la REST API documentada aquí.

Solo en la nube

Los webhooks están disponibles solo en la versión Cloud.

Los webhooks permiten que ADHDev Cloud envíe eventos de máquina y agente a tu propio endpoint HTTP.

Comportamiento actual importante:

  • la API de webhooks está activa
  • la página dedicada /webhooks del panel no es actualmente una superficie de navegación estándar estable
  • usa la referencia de la REST API como el contrato canónico para las cargas útiles, los eventos y las formas del historial de entrega
  • las acciones de crear / alternar / eliminar / probar webhook son operaciones de cuenta de la nube protegidas por inicio de sesión reciente y requieren un JWT de sesión de panel nuevo, no una clave de API

Crear un webhook

Crea el webhook desde una sesión de panel de la nube con la sesión actualmente iniciada. El cuerpo de la solicitud subyacente es:

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

Si llamas a los endpoints de webhook que mutan desde una sesión de navegador obsoleta o con una clave de API, el servidor devuelve 403 RECENT_LOGIN_REQUIRED en lugar de aprovisionar el hook.

La respuesta de creación devuelve:

  • el registro del webhook
  • un secret mostrado una vez para la verificación de firma

Usa ["*"] en events para suscribirte a todos los eventos compatibles.

Eventos

EventoDisparador
agent:generating_startedEl agente empezó a generar una respuesta
agent:generating_completedEl agente terminó de generar
agent:waiting_approvalEl agente está esperando aprobación
agent:errorEl agente encontró un error
webhook:testEntrega de prueba solicitada explícitamente

Formato de la carga útil

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

Verificación de firma

Cada solicitud de webhook incluye:

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

El formato de la firma es:

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

Verifícala contra el cuerpo de la solicitud en bruto.

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

Tu secreto de webhook se muestra una vez cuando creas el webhook — guárdalo de forma segura.

Endpoints de gestión

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

Los endpoints GET son la superficie de automatización más segura. Los endpoints que mutan (POST, PATCH, DELETE, test) son operaciones de sesión de panel protegidas por inicio de sesión reciente.

Política de reintentos

Las entregas fallidas se reintentan hasta 3 veces con backoff exponencial.

Límites de plan

PlanMáx. webhooks
Free2
Pro10
Team50
EnterpriseIlimitado

La documentación de la nube alojada está aquí. La documentación de código abierto y autoalojada está en el repositorio OSS.