---
title: "Surge Webhook"
method: POST
path: "/telephony/webhooks/surge"
tags: ["telephony"]
---

# Surge Webhook

`POST /telephony/webhooks/surge`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/telephony/webhooks/surge`
- Auth: none declared

Every Surge SMS event: message.sent/delivered/failed, message.received,
contact.opted_out/opted_in. ONE endpoint for all of them — Surge registers
a single project-level webhook URL in its dashboard (there is no per-message
callback URL and no API to register one), so the event type inside the
envelope is the router.

PUBLIC, authenticated solely by the Standard Webhooks signature, mirroring
the Twilio voice webhooks. Note the signature covers
`webhook-id.webhook-timestamp.<raw body>` and NOT the URL, so unlike the
Twilio validator this needs no TELEPHONY_WEBHOOK_BASE_URL.

THE BODY IS READ AS RAW BYTES BEFORE ANYTHING PARSES IT. Re-serializing
parsed JSON changes whitespace and key order and would invalidate every
genuine signature.

THREE RESPONSE CLASSES, AND THE DISTINCTION IS THE CONTRACT:

- **403** — bad, missing, or stale signature. Authentication failure only.
- **200 `{"status": "ok"}`** — accepted. Surge's webhook spec documents
  200 explicitly ("Return a 200 status to indicate that the data was
  received successfully"), so this returns 200 rather than a bare 204.
  This covers PERMANENT failures too: a body we cannot parse, an event we
  cannot correlate, a type we do not know. None of those improve on a
  retry, and non-2xx would buy an exponential-backoff retry storm.
- **500** — a TRANSIENT upstream failure (see SurgeTransientError) is
  allowed to propagate so Surge redelivers. Acknowledging a blip would
  turn a recoverable failure into a permanently lost opt-out.

## Response `200`

Successful Response

- unknown

---

[API](https://skmtc.dev/verdun/apis/verdun-api.md) - [All operations](https://skmtc.dev/verdun/apis/verdun-api/llms.txt) - [OpenAPI document](https://skmtc.dev/verdun/apis/verdun-api/revisions/35a2a6ebedda?raw)
