Webhook Payloads
3 min read
Outgoing webhook actions (automation rules and the global webhook) deliver JSON payloads with a consistent envelope and event-specific data. This page documents the payload structure for every trigger event so receivers can be implemented against a clear contract.
Common Envelope #
Every payload has the same top-level shape:
{
"event": "...",
"delivery_id": "...",
"timestamp": 1710000000,
"rule": {
"id": 42,
"name": "..."
},
"data": { ... }
}
| Field | Description |
|---|---|
| event | Trigger event ID (e.g. chargeback_filed) |
| delivery_id | UUID; same across retries of the same delivery |
| timestamp | Unix timestamp at dispatch (changes on retry) |
| rule.id, rule.name | The automation rule that triggered this webhook |
| data | Event-specific payload (documented per-event below) |
Headers also included:
Content-Type: application/jsonX-TrustLens-Event: event IDX-TrustLens-Signature: HMAC-SHA256 of raw body, formatsha256=hex...X-TrustLens-Delivery: same as delivery_idX-TrustLens-Timestamp: same as timestamp
Customer Data Shape #
Many events include a customer object in data:
"customer": {
"email_hash": "...",
"email": "...",
"trust_score": 47,
"segment": "caution",
"is_blocked": false,
"is_allowlisted": false,
"total_orders": 12,
"total_refunds": 3,
"return_rate": 25.0,
"total_disputes": 0,
"linked_accounts_count": 0,
"first_order_date": "2023-04-15T10:30:00Z",
"last_order_date": "2024-03-10T14:22:00Z"
}
Order Data Shape #
"order": {
"id": 5432,
"total": 159.99,
"subtotal": 145.00,
"shipping_total": 9.99,
"tax_total": 5.00,
"coupon_total": 0.00,
"currency": "USD",
"item_count": 3,
"payment_method": "stripe",
"shipping_country": "US",
"billing_country": "US",
"status": "processing",
"created_at": "2024-03-15T12:00:00Z"
}
Per-Event Payloads #
score_changed #
"data": {
"customer": { ... },
"old_score": 55,
"new_score": 47,
"score_delta": -8
}
segment_changed #
"data": {
"customer": { ... },
"old_segment": "normal",
"new_segment": "caution"
}
order_placed #
"data": {
"customer": { ... },
"order": { ... }
}
order_refunded #
"data": {
"customer": { ... },
"order": { ... },
"refund": {
"id": 5433,
"amount": 49.99,
"reason": "Customer didn't like item",
"is_full_refund": false
}
}
order_cancelled #
"data": {
"customer": { ... },
"order": { ... },
"cancelled_by": "customer"
}
chargeback_filed #
"data": {
"customer": { ... },
"order": { ... },
"dispute": {
"id": 123,
"dispute_id": "dp_xyz789",
"brand": "visa",
"amount": 99.00,
"reason": "fraudulent",
"status": "open",
"source": "auto",
"filed_at": "2024-03-10T08:00:00Z"
}
}
dispute_status_changed #
"data": {
"customer": { ... },
"dispute": { ... },
"old_status": "open",
"new_status": "lost"
}
linked_accounts_detected #
"data": {
"customer": { ... },
"linked": [
{
"email_hash": "...",
"segment": "critical",
"link_types": ["shipping_address", "ip", "device"]
}
],
"total_linked_count": 3
}
fraud_ring_detected #
"data": {
"customer": { ... },
"linked_critical": [
{ "email_hash": "...", "segment": "critical" },
{ "email_hash": "...", "segment": "critical" }
]
}
card_testing_attack #
"data": {
"fingerprint_hash": "...",
"country": "DE",
"decline_count_60s": 5,
"decline_count_10m": 12,
"lockout_duration_seconds": 90,
"recent_decline_codes": {
"insufficient_funds": 3,
"invalid_expiry": 2
}
}
auto_escalated #
"data": {
"contributing_fingerprints": ["hash1", "hash2", "hash3"],
"countries_represented": ["DE", "RU", "BR"],
"single_country_max_share": 0.45,
"panic_freeze_expires_at": 1710000900
}
panic_button_activated #
"data": {
"source": "manual",
"admin_user_id": 42,
"admin_username": "[email protected]",
"freeze_duration_seconds": 900,
"freeze_expires_at": 1710000900
}
shipping_anomaly #
"data": {
"customer": { ... },
"anomaly_type": "address_hopping",
"details": {
"distinct_addresses_30d": 4
}
}
coupon_applied #
"data": {
"customer": { ... },
"order": { ... },
"coupon": {
"code": "WELCOME10",
"is_first_order": true,
"discount_amount": 5.00
}
}
coupon_abuse #
"data": {
"customer": { ... },
"abuse_type": "first_order_repeat",
"details": {
"first_order_coupons_count": 3
}
}
chargeback_ratio_threshold_crossed #
"data": {
"brand": "visa",
"current_ratio": 0.87,
"threshold": 0.90,
"warn_percent": 80,
"total_disputes_month": 105,
"total_orders_month": 12000
}
Field Type Notes #
- Timestamps: ISO 8601 UTC for human-readable fields; Unix epoch for the envelope timestamp
- Monetary amounts: Decimal numbers (not strings); use receiver’s currency-handling logic
- Hashes: 32-character lowercase hex strings (SHA-256 truncated)
- Enums: Lowercase strings matching the database enum values
Backward Compatibility #
Receivers should:
- Ignore unknown fields (forward-compatible)
- Not depend on field order (JSON objects are unordered)
- Handle missing fields gracefully (some events may add fields in future versions)
Breaking changes to payloads are rare and announced in changelog. Minor additions happen routinely.
Testing #
For testing receivers without waiting for real events, use the “Send Test Webhook” feature in Settings → Webhooks. It dispatches a synthetic payload with realistic test data so you can verify your receiver’s parsing and signature verification.