563848e0ecc0
Receive SendGrid delivery-status events for outreaches
Accepts a batch of email delivery-status events (delivered, bounced, opened, clicked, dropped, deferred, etc.) posted by SendGrid's Event Webhook and applies each one to the matching outreach email record. Configure this URL in SendGrid's Event Webhook settings for outreach sender identities; use the sibling POST /outreach/sendgrid/webhook/incoming-parse endpoint instead for inbound reply emails. The request body must be a non-empty JSON array of event objects; each event should carry outreach context (tenantId/emailId/outreachId) as top-level fields or nested under a custom_args object, and falls back to matching by sg_message_id alone when that context is absent. This call returns 200 immediately after starting processing: the delivery-status updates and the best-effort audit copy (raw payload to Cloud Storage plus a WebhookRawBlob record) all happen asynchronously in the background after the response is sent, so a 200 does not guarantee any individual event was actually applied. A body that is not a JSON array, an empty array, or an array with no event carrying a usable sg_message_id/event pair is not treated as an error - it still returns 200 and applies nothing. This is a public endpoint that does not require authentication; no tenant-id header is used.
Headers
Tenant ID
Request body
Example request
[
{
"email": "jane.doe@example-clinic.com",
"timestamp": "1700000000",
"event": "delivered",
"category": "credentialing-outreach",
"sgMessageId": "14c5d75ce93.filterdrecv.recvd-1-B.0",
"smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-555>",
"response": "250 2.0.0 OK",
"attempt": "1",
"status": "5.1.1",
"reason": "550 5.1.1 The email account does not exist",
"type": "bounce",
"eventTime": "2022-03-10T16:15:50Z"
}
]Response
Processing was started (or intentionally skipped for an empty/invalid batch). The JSON body is a bare string, not an object: "Processing N email status update events" when at least one event carried a usable sg_message_id/event pair (updates continue in the background); "No events to process" when the body was not a non-empty JSON array; or "No valid events to process" when it was an array but no event carried a usable sg_message_id/event pair. None of these are errors.