Webhooks
GitForge only ships one webhook endpoint today — the GitHub App webhook the bot listens on. Outbound webhooks (notify your services on bounty events) are on the roadmap; jump to Coming soon for the planned shape.
Inbound: GitHub App
Endpoint
https://api.gitgrant.app/webhook/githubMethod
POST
Signature
x-hub-signature-256 (HMAC-SHA256 with GITHUB_WEBHOOK_SECRET). Required in production.Idempotency
x-github-delivery is recorded; duplicate deliveries are dropped before any chain or DB writes.Rate limit
max(120, RATE_LIMIT_PER_MINUTE * 2) per minute per IP.Subscribed events
| Event | Action | What the bot does |
|---|---|---|
| issue_comment | created | Parses the comment. /bounty <amount> <token> replies with a funding link. /claim creates a one-time intent and DMs the contributor. |
| pull_request | closed (merged: true) | If the PR body contains 'Closes #N' and a Submitted bounty exists for that issue, calls release() on escrow and posts a confirmation comment. |
Required permissions
Issues
read & write
Pull requests
read
Metadata
read
Contents
read
Setting it up on a fresh App
1
Create the GitHub App
github.com/settings/apps/new — pick a name, homepage URL, and uncheck "Active" webhook for now.
2
Set Webhook URL and secret
Webhook URL:
https://api.gitgrant.app/webhook/github. Generate a strong secret (32+ random bytes) and store it as GITHUB_WEBHOOK_SECRET in the bot's env.3
Subscribe to events
In Subscribe to events, tick
Issue comment and Pull request.4
Generate a private key
Generate a private key downloads a
.pem file. Either mount it on the bot's host as GITHUB_PRIVATE_KEY_PATH, or paste the contents into GITHUB_PRIVATE_KEY (newlines escaped as \n).5
Install on a repo
From the App page, click Install and pick a repo to test on. You can do this from /install too.
6
Verify delivery
Open the App's Advanced tab and click Redeliver on the most recent ping. The bot logs the delivery; if signature verification fails you'll see
Invalid webhook signature in the logs.Verifying signatures yourself
If you fork the bot or run a parallel listener, verify signatures with the same secret:
import { verify } from "@octokit/webhooks-methods";
const ok = await verify(
process.env.GITHUB_WEBHOOK_SECRET!,
rawBodyString,
request.headers["x-hub-signature-256"]!,
);
if (!ok) throw new Error("invalid signature");Outbound webhooks (coming soon)
Planned: subscribe a URL to bounty lifecycle events so your treasury or accounting tools can react. Same signature scheme as GitHub (HMAC-SHA256). Events:
bounty.createdbounty.claimedbounty.submittedbounty.releasedbounty.cancelled/bounty.expired/bounty.disputed
Tracking issue and design notes will land in the docs once the contract events have a stable indexer backing them.