Webhook Payloads
5 min read
TrustLens delivers JSON payloads over two separate webhook paths, and they do not share a payload shape. This page documents the exact body and headers each one sends so receivers can be implemented against the real contract.
- Global webhook endpoints (Settings → Webhooks) — fire on a fixed set of customer/order lifecycle events. Flat payload, one shape per event.
- Automation-rule webhooks (the
send_webhookaction on a Pro automation rule) — fire whenever a rule with that action matches. Every one of these carries the sametrustlens_automationenvelope regardless of which trigger fired it.
Global Webhook Events #
Global endpoints emit exactly these event strings (the value of the top-level event field and the X-TrustLens-Event header):
| Event | Fires when |
|---|---|
score_updated |
A customer’s trust score is recalculated |
customer_blocked |
A customer is blocked |
customer_unblocked |
A block is removed |
customer_allowlisted |
A customer is allowlisted |
customer_allowlist_removed |
An allowlist entry is removed |
checkout_blocked |
A checkout is blocked by enforcement |
high_risk_order |
An order is placed by a customer in the risk or critical segment |
automation_triggered |
A Pro automation rule fires (one event per matched rule) |
Each endpoint can subscribe to a subset of these; the global “Events to Send” setting controls which fire by default (score_updated, customer_blocked, checkout_blocked, high_risk_order out of the box).
Global Webhook Envelope #
Global payloads are flat — there is no nested data wrapper. Every global payload has at minimum:
{
"event": "score_updated",
"timestamp": "2024-03-15T12:00:00+00:00",
"customer": { ... },
"site": {
"url": "https://store.example.com",
"name": "Example Store"
}
}
| Field | Description |
|---|---|
| event | Event ID (one of the strings in the table above) |
| timestamp | ISO 8601 string (current_time('c')) at dispatch |
| customer | Customer object (see below); empty object if the customer record can’t be resolved |
| site | Origin store URL and name, added to every global payload |
Individual events add their own fields alongside these — documented per-event below.
Headers (global) #
Content-Type: application/jsonX-TrustLens-Event— the event IDX-TrustLens-Delivery— a UUID, unique per delivery attemptX-TrustLens-Webhook-ID— the configured endpoint’s IDX-TrustLens-Timestamp— Unix epoch at dispatchX-TrustLens-Signature— present only when the endpoint has a secret; formatsha256=hex...
Signature note: the HMAC-SHA256 is computed over timestamp + "." + raw_body (not the body alone), so receivers should reconstruct the signing string from the X-TrustLens-Timestamp header value and the raw request body. Signing the timestamp lets you reject replays by checking the timestamp is recent (a 5-minute window is recommended).
Customer Object #
The customer object on global events contains:
"customer": {
"email_hash": "...",
"email": "...",
"trust_score": 47,
"segment": "caution",
"total_orders": 12,
"total_refunds": 3,
"return_rate": 25.0,
"is_blocked": false,
"is_allowlisted": false
}
Per-Event Payloads (Global) #
score_updated #
{
"event": "score_updated",
"timestamp": "...",
"customer": { ... },
"new_score": 47,
"new_segment": "caution",
"site": { ... }
}
customer_blocked #
{
"event": "customer_blocked",
"timestamp": "...",
"customer": { ... },
"reason": "Manual block by admin",
"site": { ... }
}
customer_unblocked / customer_allowlisted / customer_allowlist_removed #
{
"event": "customer_unblocked",
"timestamp": "...",
"customer": { ... },
"site": { ... }
}
These three carry only the standard envelope plus the customer object — no extra event-specific fields.
checkout_blocked #
{
"event": "checkout_blocked",
"timestamp": "...",
"customer": { ... },
"email": "[email protected]",
"site": { ... }
}
automation_triggered #
{
"event": "automation_triggered",
"timestamp": "...",
"customer": { ... },
"rule": {
"id": 42,
"name": "Block critical at checkout",
"trigger": "checkout_blocked"
},
"action": "block_customer",
"order_id": 5432,
"site": { ... }
}
order_id is null when the action wasn’t tied to an order.
high_risk_order #
{
"event": "high_risk_order",
"timestamp": "...",
"customer": { ... },
"order": {
"id": 5432,
"number": "5432",
"total": 159.99,
"currency": "USD",
"status": "processing"
},
"site": { ... }
}
Only sent when the ordering customer is in the risk or critical segment; orders from healthier segments never fire this event.
Automation-Rule Webhooks #
The send_webhook action on a Pro automation rule posts a single, fixed envelope. The event is always trustlens_automation — the specific trigger that fired the rule is carried in the trigger field, not in event. There is no per-trigger payload variation and no nested data wrapper.
{
"event": "trustlens_automation",
"rule": "Block critical at checkout",
"rule_id": "42",
"trigger": "checkout_blocked",
"email_hash": "...",
"trust_score": 18,
"segment": "critical",
"fired_at": "2024-03-15 12:00:00",
"attempt": 1
}
| Field | Description |
|---|---|
| event | Always the literal trustlens_automation |
| rule, rule_id | Name and ID of the rule whose send_webhook action fired |
| trigger | The automation trigger key that matched (e.g. checkout_blocked, score_updated, chargeback_filed) |
| email_hash | Target customer’s email hash |
| trust_score, segment | Current score/segment at fire time; null if the customer can’t be resolved |
| fired_at | Local MySQL datetime at dispatch |
| attempt | 1 on first try; increments on each retry |
Headers (automation) #
Content-Type: application/jsonX-TrustLens-Event: trustlens_automationX-TrustLens-Delivery— a UUID per attemptX-TrustLens-Rule-ID— the rule IDX-TrustLens-Timestamp— Unix epoch at dispatchX-TrustLens-Signature—sha256=hex..., signed by default with the per-install automation secret (overridable via thetrustlens/automation/webhook_secretfilter)
Automation webhooks are dispatched blocking with up to 3 retries on non-2xx (60s / 120s / 240s backoff). See Async Dispatch & Retries for the full retry model.
Field Type Notes #
- Timestamps: global payloads use an ISO 8601 string in
timestamp; automation payloads use a local MySQL datetime infired_at; both signature schemes use the Unix epoch from theX-TrustLens-Timestampheader. - Monetary amounts: decimal numbers (not strings).
- Hashes: lowercase hex email hashes.
- Enums: lowercase strings matching the database/segment values.
Backward Compatibility #
Receivers should:
- Ignore unknown fields (forward-compatible)
- Not depend on field order (JSON objects are unordered)
- Handle missing fields gracefully (e.g. an empty
customerobject when the record can’t be resolved)
Breaking changes to payloads are rare and announced in the 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 payload with event: "test" and the standard headers so you can verify your receiver’s parsing and signature verification end to end.
Updated on June 18, 2026