You do not call this endpoint directly. GitHub sends the request automatically on every push event. The information below is provided so you understand what Shipyard expects and how to troubleshoot delivery failures in GitHub’s webhook settings.
POST /api/webhook
Receives a GitHub push event, verifies the HMAC-SHA256 signature, matches the repository URL and branch to a project, inserts a build record, and starts the build pipeline asynchronously. No JWT auth — authenticated via HMAC-SHA256 signature.Required headers
| Header | Description |
|---|---|
X-Hub-Signature-256 | HMAC-SHA256 signature computed by GitHub using your WEBHOOK_SECRET. Format: sha256=<hex>. Shipyard computes the same HMAC over the raw request body and compares using a timing-safe equality check. |
X-GitHub-Event | Event type. Shipyard only processes push events. A ping event (sent when the webhook is first registered) returns 200 without triggering a build. |
Content-Type | Must be application/json. Set automatically by GitHub when you configure the webhook’s content type as JSON. |
Request body
The request body is the standard GitHub push event payload, sent automatically by GitHub. Shipyard reads the following fields:The HTTPS URL of the repository (e.g.,
https://github.com/owner/repo). Shipyard uses this to find the matching project in the database.The full Git ref of the pushed branch, in the format
refs/heads/<branch>. Shipyard strips the refs/heads/ prefix and compares the result against the project’s configured branch. If they do not match, no build is triggered.The commit message of the most recent commit in the push. Stored as the build’s
commit field.The name of the commit author. Stored as the build’s
commitAuthor field.The full SHA of the HEAD commit after the push. Stored as the build’s
commitHash and used during the clone step to check out the exact revision. Also used as the commit hash if a rollback to this build is requested later.What Shipyard does with the payload
- Verifies the
X-Hub-Signature-256header using HMAC-SHA256 withWEBHOOK_SECRET. Returns401if the signature is missing or does not match. - Checks the
X-GitHub-Eventheader. Returns200forping, proceeds forpush, and ignores other events. - Strips
refs/heads/fromrefto get the branch name. - Queries the database for a project whose
repoUrlmatchesrepository.html_urland whosebranchmatches the extracted branch name. Returns404if no match is found. - Inserts a new build record with
status: "queued"and responds201. - Starts the build pipeline asynchronously (clone, Dockerfile generation, Docker build, test run, deploy).
Response
On success (matching project found and build queued):Error responses
| Status | Condition |
|---|---|
401 | X-Hub-Signature-256 header is missing |
401 | Signature does not match the computed HMAC — payload may be tampered or WEBHOOK_SECRET is wrong |
404 | No project found whose repoUrl and branch match the push event |
500 | Failed to insert the build record |
Troubleshooting webhook deliveries
GitHub logs every webhook delivery attempt, including the request headers, payload, and response code. To inspect failed deliveries:- Go to your repository on GitHub
- Open Settings → Webhooks
- Click on the Shipyard webhook entry
- Scroll to Recent Deliveries to see the response code and body for each delivery
401 responses:
WEBHOOK_SECRETin your.envdoes not match the secret stored in GitHub’s webhook configuration. Update one to match the other and redeliver.- The request body was modified in transit (e.g., by a reverse proxy that re-serializes JSON). Shipyard computes the HMAC over the raw body — any reformatting will break the signature.
404 responses:
- The repository URL stored on the project uses HTTPS (
https://github.com/owner/repo) but the webhook payload’srepository.html_urldiffers (e.g., has a trailing.git). Check that therepoUrlrecorded in Shipyard matches the format GitHub sends exactly. - The push targeted a branch that is not configured on the project. Only pushes to the branch specified at project creation (or last updated via
PUT /api/project/projects/:projectId) trigger a build.