Skip to main content
Marmar supports multiple webhooks per tenant, allowing you to route assessment notifications to different endpoints based on your architecture.

Creating Webhooks

Create webhooks via POST /v1/webhooks. The secret is auto-generated and returned only in the creation response:
// Request
{
  "name": "Production Handler",
  "url": "https://your-server.com/webhooks/marmar",
  "events": ["assessment.completed"]
}

// Response
{
  "webhook": {
    "id": "abc-123",
    "name": "Production Handler",
    "url": "https://your-server.com/webhooks/marmar",
    "events": ["assessment.completed"],
    "status": "active",
    "createdAt": "2026-01-13T00:00:00Z"
  },
  "secret": "f47ac10b-58cc-4372-a567-0e02b2c3d479-ab12cd34ef56..."
}
Important: Store the secret securely—it won’t be shown again.

Managing Webhooks

EndpointDescription
GET /v1/webhooksList all webhooks
GET /v1/webhooks/{id}Get a specific webhook
PATCH /v1/webhooks/{id}Update name, URL, events, or status
DELETE /v1/webhooks/{id}Delete a webhook
POST /v1/webhooks/{id}/regenerate-secretGet a new secret (invalidates old)

Status Values

  • active — Webhook receives deliveries
  • paused — Temporarily disabled
  • disabled — Permanently disabled

Signature Verification

Each delivery includes headers:
  • X-Marmar-Event: Event type (e.g., assessment.completed)
  • X-Marmar-Timestamp: Unix timestamp in seconds
  • X-Marmar-Signature: v1= + HMAC-SHA256 hex digest
  • X-Marmar-Webhook-Id: ID of the webhook that triggered delivery
Verify signatures using constant-time comparison:
const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(timestamp + '.' + body)
  .digest('hex');
const isValid = `v1=${expected}` === signature;
Reject payloads older than 5 minutes or with invalid signatures.

Retries

Failed deliveries (non-2xx, timeout, network error) retry with exponential backoff up to 15 minutes.