Inbound Delivery Tracking
Signed inbound webhooks that map provider delivery events onto communication_log status updates.
Overview
POST /api/v1/notifications/inbound/{provider} (api.v1.notifications.inbound) accepts a signed delivery-tracking webhook. Auth is signature-only — there is no Sanctum token. Core registers no production resolvers; plugins supply them through PluginRegistrar::deliveryTrackingResolver() onto DeliveryTrackingResolverRegistry. Unknown provider keys return 404.
Signature
Per-provider secrets live in settings as notifications.inbound_{provider}_secret. Header names and clock skew default to:
| Setting | Default |
|---|---|
notifications.inbound_{provider}_signature_header |
notifications.inbound_signature_header → X-Signature |
notifications.inbound_{provider}_timestamp_header |
notifications.inbound_timestamp_header → X-Timestamp |
notifications.inbound_tolerance_seconds |
300 |
SignedInboundRequest verifies the signature or aborts 401.
Resolution and queue
A registered resolver maps the JSON body to DeliveryTrackingUpdateData. An unrecognised payload returns 422 { "message": "Unrecognised payload." }. A recognised payload is dispatched as ApplyDeliveryTrackingUpdate on the notifications queue and the HTTP response is 202 { "status": "accepted" }.
The job updates the matching communication_log row through the delivery-status machine — it is not a second send.