Webhooks

Webhooks

Configure webhooks to receive notifications when actions complete.

Create Webhook Endpoint

First, create a webhook endpoint to receive notifications:

POST /webhooks/v1
POST
/webhooks/v1
curl -X POST https://api.case.dev/webhooks/v1 \
  -H "Authorization: Bearer sk_case_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://your-app.com/webhooks/actions",
  "description": "Action notifications",
  "events": [
    "action.completed",
    "action.failed"
  ]
}'

Response:

{
  "id": "webhook_abc123",
  "url": "https://your-app.com/webhooks/actions",
  "secret": "whsec_fb563729c3e2e4b54fbc551c...",
  "events": ["action.completed", "action.failed"],
  "createdAt": "2024-11-06T20:00:00Z"
}

⚠️ Important: Save the secret - it's only shown once and used to verify webhook signatures.

Webhook Events

Subscribe to these events:

  • action.started - Execution began
  • action.completed - Execution finished successfully
  • action.failed - Execution failed with error
  • action.step_completed - Individual step completed (coming soon)

Webhook Payload

When an action completes, we POST to your webhook URL:

Headers:

X-CaseMark-Signature: sha256=abc123...
X-CaseMark-Event: action.completed
X-CaseMark-Execution-Id: exec_xyz789
Content-Type: application/json

Body:

{
  "event_type": "action.completed",
  "execution_id": "exec_xyz789",
  "action_id": "action_abc123",
  "action_name": "Deposition Analysis Pipeline",
  "status": "completed",
  "output": {
    "summary": "...",
    "key_admissions": [...]
  },
  "step_results": {
    "summarize": {...},
    "extract_admissions": {...}
  },
  "duration_ms": 45000,
  "completed_at": "2024-11-06T20:01:00Z"
}

Verify Webhook Signature

Verify webhook authenticity using HMAC SHA-256:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = `sha256=${crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex')}`;
    
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/actions', (req, res) => {
  const signature = req.headers['x-casemark-signature'];
  const payload = req.body;
  
  if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook
  console.log('Action completed:', payload.execution_id);
  res.status(200).send('OK');
});

Attach Webhook to Actions

Option 1: Set default webhook in an action definition:

POST /actions/v1
{
  "name": "My Action",
  "webhook_id": "webhook_abc123",
  "definition": {...}
}

Option 2: Override per execution:

POST /actions/v1/{id}/execute
{
  "input": {...},
  "webhook_id": "webhook_xyz789"
}

Response:

{
  "data": [
    {
      "id": "delivery_123",
      "eventType": "action.completed",
      "executionId": "exec_xyz",
      "responseCode": 200,
      "deliveredAt": "2024-11-06T20:01:00Z",
      "error": null
    }
  ]
}