Total Access Docs
API Reference

Webhook Payload Customization

Customize outbound webhook payloads with field selection, templates, and per-event overrides

Webhook Payload Customization

TotalAccess allows you to customize the payload sent to your webhook endpoints. This guide covers the three customization modes, per-event template overrides, and live preview.

Overview

Each webhook can be configured with a payload template that transforms the default payload before delivery. The payload_template field on the webhook configuration accepts a JSON object with the following structure:

{
  "mode": "passthrough | fields | template",
  "fields": ["event", "data.id", "data.status"],
  "template": { "event_type": "{{ event }}", "id": "{{ data.id }}" },
  "per_event": {
    "job.completed": { "mode": "fields", "fields": ["event", "data.work_item_id"] }
  }
}

Modes

1. Passthrough (Default)

Sends the full payload as-is. No transformation is applied.

{
  "mode": "passthrough"
}

Example output:

{
  "event": "job.completed",
  "version": "1.0",
  "timestamp": "2026-07-22T14:30:00Z",
  "data": {
    "work_item_id": "550e8400-...",
    "status": "completed",
    "title": "Install solar panels",
    "assigned_to": { "id": 1, "name": "John Doe" }
  },
  "metadata": { "client_id": 1 }
}

2. Field Selection

Includes only the specified field paths from the payload. Uses dot notation for nested fields.

{
  "mode": "fields",
  "fields": ["event", "data.work_item_id", "data.status", "timestamp"]
}

Example output:

{
  "event": "job.completed",
  "data": {
    "work_item_id": "550e8400-...",
    "status": "completed"
  },
  "timestamp": "2026-07-22T14:30:00Z"
}

Field paths use dot notation (e.g., data.assigned_to.name). Only existing fields are included — missing paths are silently skipped.

3. Custom Template

Define a custom JSON structure using {{ field.path }} interpolation. The template is a JSON object where string values can contain interpolation expressions.

{
  "mode": "template",
  "template": {
    "event_type": "{{ event }}",
    "job_id": "{{ data.work_item_id }}",
    "status": "{{ data.status }}",
    "assignee": "{{ data.assigned_to.name }}",
    "completed_at": "{{ timestamp }}"
  }
}

Example output:

{
  "event_type": "job.completed",
  "job_id": "550e8400-...",
  "status": "completed",
  "assignee": "John Doe",
  "completed_at": "2026-07-22T14:30:00Z"
}

Per-Event Template Overrides

You can define different templates for specific event types within a single webhook. The per_event field maps event names to template configurations.

{
  "mode": "fields",
  "fields": ["event", "data.id", "data.status", "timestamp"],
  "per_event": {
    "job.completed": {
      "mode": "template",
      "template": {
        "type": "job_done",
        "id": "{{ data.work_item_id }}",
        "completed_by": "{{ data.assigned_to.name }}"
      }
    },
    "job.created": {
      "mode": "passthrough"
    }
  }
}

When an event is delivered:

  1. If per_event contains an entry for the event, that template is used
  2. Otherwise, the default (top-level) template is applied

Per-event overrides are useful when different events have different consumer requirements — e.g., a compact payload for status updates but a full payload for creation events.

Template Preview

The OutboundWebhookModal includes a live preview tool that renders your template against sample data:

  1. Select an event type from the dropdown
  2. Click Preview to see the rendered output
  3. The sample input and rendered output are displayed side-by-side

You can also use the API directly:

POST /api/v1/work-items/webhooks/template-preview
Content-Type: application/json
Authorization: Bearer <token>

{
  "event": "job.completed",
  "template": {
    "mode": "fields",
    "fields": ["event", "data.work_item_id", "data.status"]
  }
}

Response:

{
  "success": true,
  "event": "job.completed",
  "sample_payload": {
    "event": "job.completed",
    "version": "1.0",
    "timestamp": "2026-07-22T14:30:00Z",
    "data": {
      "work_item_id": "550e8400-...",
      "status": "completed",
      "title": "Sample Work Item"
    }
  },
  "rendered_payload": {
    "event": "job.completed",
    "data": {
      "work_item_id": "550e8400-...",
      "status": "completed"
    }
  }
}

DLQ Alerts

Each webhook can be configured with DLQ (Dead Letter Queue) alert settings:

FieldTypeDefaultDescription
dlq_alert_enabledbooleanfalseEnable DLQ alerts for this webhook
dlq_alert_thresholdinteger10Alert when DLQ count exceeds this in 24h
dlq_alert_emailstringnullRecipient email (null = use webhook creator's email)

When enabled, an alert email is sent when the number of dead-lettered deliveries in the past 24 hours exceeds the threshold. Alerts are rate-limited to 1 per hour per webhook.

Configuration via API

PATCH /api/v1/work-items/webhooks/:id
Content-Type: application/json
Authorization: Bearer <token>

{
  "dlq_alert_enabled": true,
  "dlq_alert_threshold": 5,
  "dlq_alert_email": "[email protected]"
}

Configuration via UI

In the OutboundWebhookModal, scroll to the DLQ Alert Configuration section:

  1. Check "Enable DLQ alerts for this webhook"
  2. Set the threshold (number of DLQ items in 24h before alerting)
  3. Optionally specify an alert email (defaults to the webhook creator's email)

Auto-Expiry

Dead-lettered deliveries are automatically expired after 30 days (configurable) by the webhook maintenance cron job:

POST /api/v1/cron/webhook-maintenance
x-cron-secret: <secret>

{
  "dlq_retention_days": 30
}

Expired items are marked with status = 'expired' and the reason is appended to dlq_reason.

Signing Key Rotation

When a signing key is rotated:

  1. A new key is generated and becomes the active signing key
  2. The old key enters a grace period (default: 72 hours)
  3. Both keys are valid for signature verification during the grace period
  4. An email notification is sent to the webhook owner
  5. After the grace period, the old key is automatically deactivated

Rotation Notification

The notification email includes:

  • New key version
  • Grace period duration
  • Old key validity end time
  • Action required message

Auto-Deactivation

The webhook maintenance cron job automatically deactivates keys whose grace period has ended:

POST /api/v1/cron/webhook-maintenance
x-cron-secret: <secret>

This runs both cleanupExpiredDlqItems and cleanupExpiredKeys in a single call.

On this page