API Reference / webhooks

Webhooks

Receive real-time event notifications from the DramWell API — event types, payload structure, signature verification, and retry behavior.

Overview

Webhooks let you receive real-time notifications when things happen in DramWell. Instead of polling the API, register an HTTPS endpoint and we will send you a POST request every time a relevant event fires. Webhooks are the recommended way to keep external systems in sync with DramWell data.


Event Types

Event Description
job.created A new job has been created
job.updated A job's status, assignment, or details changed
job.completed A job has been marked complete
invoice.created A new invoice has been generated
invoice.paid An invoice payment has been successfully collected
invoice.voided An invoice has been voided
customer.created A new customer record has been created
customer.updated A customer's information has changed
membership.enrolled A customer has enrolled in a membership plan
membership.cancelled A membership plan has been cancelled
membership.renewed A membership plan has been renewed

Payload Structure

Every webhook delivery is a POST request with a JSON body:

{
  "id": "evt_01HXYZ",
  "type": "invoice.paid",
  "created_at": "2026-03-10T14:32:00Z",
  "org_id": "org_01HABC",
  "data": {
    "id": "inv_01HDEF",
    "amount": 32500,
    "currency": "usd",
    "customer_id": "cus_01HGHI",
    "paid_at": "2026-03-10T14:31:58Z"
  }
}
Field Type Description
id string Unique event ID — use this to deduplicate deliveries
type string The event type
created_at ISO 8601 string When the event was generated
org_id string The organization the event belongs to
data object The affected resource at the time of the event

Signature Verification

Every delivery includes a X-DramWell-Signature header. You must verify this signature before processing the payload to ensure the request genuinely came from DramWell.

The signature is an HMAC-SHA256 hash of the raw request body, computed using your webhook secret as the key, then base64-encoded.

import crypto from 'crypto'

function verifyWebhook(
  rawBody: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('base64')

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

Always use timingSafeEqual to prevent timing attacks. Reject requests that fail verification with a 400 response.


Retry Policy

If your endpoint returns anything other than a 2xx response — or does not respond within 10 seconds — DramWell will retry the delivery:

Attempt Delay after previous failure
1 Immediate
2 5 minutes
3 30 minutes
4 2 hours
5 8 hours

After 5 failed attempts the event is marked as undelivered and logged in the admin panel under Settings > Webhooks > Delivery Log. You can replay any event manually from that log.


Registering a Webhook

Via admin panel

  1. Go to Settings > Webhooks in the admin panel.
  2. Click Add Endpoint.
  3. Enter your HTTPS URL and select the event types you want to receive.
  4. Copy the generated webhook secret and store it securely.

Via API

POST /v1/webhooks
Authorization: Bearer sk_live_xxxx
Content-Type: application/json

{
  "url": "https://your-app.example.com/webhooks/dramwell",
  "events": ["job.completed", "invoice.paid", "membership.enrolled"]
}

Best Practices

  • Respond with 200 OK immediately and process the event asynchronously — never do heavy work inside the HTTP handler.
  • Use the event id field to deduplicate — your endpoint may receive the same event more than once during retries.
  • Store the raw request body before parsing JSON so signature verification can use the exact bytes we signed.
  • Use a queue (SQS, BullMQ, etc.) to buffer events and handle processing failures independently of the webhook receiver.

Related Articles

Was this article helpful?