Receive a GitHub App webhook delivery
POST/api/github/webhooks
receiveGithubWebhook
GitHub's delivery endpoint for this deployment's App. Verifies `X-Hub-Signature-256` against the App's webhook secret over the raw request bytes, then records the delivery in the inbox keyed by `X-GitHub-Delivery`. Nothing is written unless the signature verifies: a missing, malformed, or wrong signature is `401` and leaves no row. A delivery that carries no `installation.id` is `400` — every App delivery but `ping` carries one, and it is what makes the delivery addressable even when the repository it names is not bound here. A body over 8 MiB is `413`, rejected by the body reader before it is hashed. A redelivery of a delivery id already held answers `202` exactly as a first delivery does — a successful dedupe is not a failure. A delivery about a repository this deployment has not bound is still recorded (with no local repository attached), so a manual redelivery has something to dedupe against. GitHub does **not** redeliver a failed App delivery on its own, so anything refused here is lost until it is replayed by hand. A per-IP ceiling of 3000/minute applies. It exists because the 8 MiB body is buffered before the signature can be checked, so an unauthenticated caller can make this node do work; it is set far above GitHub's real delivery rate from its handful of hook egress addresses, because a `429` here loses the delivery outright. A `ping` — GitHub's handshake for a newly configured webhook — verifies like any other delivery and then answers `204` with nothing stored: it names neither an installation nor a repository, so there is nothing to address it to, and it is the one delivery exempted from the `installation.id` requirement. The payload is stored verbatim and **not interpreted** beyond reading `installation.id` and `repository.id` to address it. 404 when this deployment has no GitHub App configured.
Authentication optional — this operation also accepts anonymous requests. When authenticating, use a bearer token.
curl
curl -X POST 'https://neosource.dev/api/github/webhooks' \
-H 'Content-Type: application/json' \
-d '{}'fetch
fetch("https://neosource.dev/api/github/webhooks", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});Request bodyrequired
application/json
Responses
202Delivery recorded, or already held (a redelivery)
204A `ping` handshake: verified, deliberately not stored
401Missing or invalid `X-Hub-Signature-256`. Nothing is stored.
413The body exceeded the route's 8 MiB cap.
Standard errors
Bodies documented once for the whole API — see standard errors.
- 400Bad Request — one of: invalid_input
- 404Not Found — one of: not_found
- 429Rate limited — retry after the interval in the `Retry-After` header
- 500Internal server error
- 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
- 504Gateway timeout — the request exceeded the server's handling budget