Skip to main content

Overview

Use webhooks to receive real-time notifications from Cora when key events happen. Current outbound event types:
  • payment.success
  • payment.failed
  • call.completed
Webhook URLs are configured in the platform under Settings > Webhooks.

Events

How Delivery Works

  1. Create a webhook with a destination url and subscribedEvents. You do this in the platform UI at Settings > Webhooks.
  2. Cora generates and stores a per-webhook secret.
  3. When an event happens, Cora builds a standard webhook envelope and sends an HTTP POST to your URL.
  4. Cora logs every attempt and retries transient failures.

Request Format

Every delivery is a POST with Content-Type: application/json. Headers:
  • X-Webhook-Signature: HMAC-SHA256 hex digest of JSON.stringify(payload) signed with your webhook secret
  • X-Webhook-Event: Event name (for example payment.success)
  • X-Webhook-Timestamp: ISO-8601 timestamp from the payload
  • X-Webhook-Delivery-Id: Internal delivery log id
  • User-Agent: Cora-Webhooks/1.0
Body envelope:
{
  "event": "payment.success",
  "eventCategory": "payments",
  "organization": {
    "id": "org_123",
    "name": "Acme Corp"
  },
  "agent": {
    "id": "agent_123",
    "name": "Collections Agent"
  },
  "timestamp": "2026-02-17T18:05:21.841Z",
  "payload": {}
}
agent is only included for agent-level events where an agentId exists.

Retries, Timeouts, And Failures

  • Delivery timeout: 30s
  • Success: any 2xx response
  • Retryable HTTP status codes: 408, 429, 500, 502, 503, 504
  • Network failures are retried
  • Defaults per webhook:
    • maxRetries: 3 (total attempts: 4 including initial attempt)
    • retryDelayMs: 5000
    • exponentialBackoff: true (multiplier x5 per retry)

Verify Signatures

Example verifier in Node.js:
import crypto from "crypto";

function isValidSignature(rawBodyObject: unknown, signature: string, secret: string) {
  const payload = JSON.stringify(rawBodyObject);
  const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}