Webhooks
Patchwire accepts push events from four SCM providers. A scan fires within ~1 second of the push and finishes in under a minute for typical repositories.
URL pattern
| Provider | URL |
|---|---|
| Forgejo | https://api.patchwire.app/v1/hooks/forgejo |
| GitHub | https://api.patchwire.app/v1/hooks/github |
| GitLab | https://api.patchwire.app/v1/hooks/gitlab |
| Bitbucket Cloud | https://api.patchwire.app/v1/hooks/bitbucket |
All four endpoints reject requests whose HMAC signature does not verify against your installation's PATCHWIRE_WEBHOOK_SECRET.
Getting your secret
Open any project's page → Webhook setup card. Each provider tab shows:
- The full URL to paste
- The shared secret to paste
- The exact header / event filter to set
Copy directly from there. The secret rotates on the server side only; the UI always shows the current value.
Per-provider setup
Forgejo
- Repo → Settings → Webhooks → Add webhook → choose Forgejo.
- URL:
https://api.patchwire.app/v1/hooks/forgejo. - HTTP method:
POST. - Content type:
application/json. - Secret: paste from the setup card.
- Trigger: select Push events (the default).
- Branch filter: leave blank to fire on every branch, or set to your default branch.
- Save. Click Test delivery — you should see a green checkmark and an HTTP 200.
GitHub
- Repo → Settings → Webhooks → Add webhook.
- Payload URL:
https://api.patchwire.app/v1/hooks/github. - Content type:
application/json. - Secret: paste from the setup card.
- SSL verification: leave enabled (your endpoint uses Let's Encrypt).
- Which events? Select Just the push event.
- Active: ✅. Save.
- Open the new webhook → Recent Deliveries → Redeliver to test.
GitLab
- Project → Settings → Webhooks → Add new webhook.
- URL:
https://api.patchwire.app/v1/hooks/gitlab. - Secret token: paste from the setup card. Note: GitLab sends this in the
X-Gitlab-Tokenheader verbatim, not as an HMAC; Patchwire compares it against the configured secret in constant time. - Trigger: enable Push events.
- Save.
- Click Test → Push events.
Bitbucket Cloud
- Repository → Repository settings → Webhooks → Add webhook.
- Title: anything (e.g. "Patchwire").
- URL:
https://api.patchwire.app/v1/hooks/bitbucket. - Status: Active.
- Triggers: Repository push.
- Save. Bitbucket does not have a built-in test button — push a commit to trigger.
Bitbucket Cloud signature
Bitbucket Cloud's webhook signing differs from GitHub/Forgejo's. Patchwire verifies the X-Hub-Signature-256 header only if Bitbucket sends it — older payloads fall back to checking the request's source IP range. For high-trust setups, prefer the GitHub/GitLab/Forgejo paths.
How the org and project are resolved
The webhook body carries the repository's full_name (e.g. acme/web). Patchwire splits on / to get:
owner→ resolved as the organisation slugname→ resolved as the project slug
So if your Patchwire org is acme and you register a project with slug web, the webhook for acme/web lands correctly.
If either resolution fails, the webhook returns HTTP 200 with "status":"ignored" — this is deliberate. Returning a 4xx would make the SCM retry indefinitely.
Watching a webhook fire
API logs (via SSH):
ssh hostinger "sudo kubectl logs -n patchwire deploy/patchwire-api --tail=50 | grep -E 'cloning|scan complete|scan-bg'"You'll see:
INFO cloning repo url=… branch=main target=/tmp/.tmpXXX
INFO running semgrep path=/tmp/.tmpXXX
INFO running gitleaks path=/tmp/.tmpXXX
INFO scan-bg: scan complete scan_id=… status=completed findings=2 raw_findings=3Total time: clone (~10s) + semgrep (~30s) + gitleaks (~10s) + DB writes (~few seconds) ≈ 50–60s end-to-end.