Webhooks notify external services when events occur in your repository. Build integrations, trigger deployments, and automate workflows.
Event Types
| Event | Description |
|---|---|
push | Code pushed |
pull_request | PR opened, updated, merged |
issue | Issue created, updated, closed |
comment | Comment added |
release | Release published |
pipeline | CI/CD status changed |
agent | Agent action performed |
Creating Webhooks
Via Web UI
- Go to Settings → Webhooks
- Click Add Webhook
- Configure:
- Payload URL: Your endpoint
- Content Type:
application/json - Secret: For HMAC verification
- Events: Select which to receive
- Click Add Webhook
Via API
bash
curl -X POST /api/v1/repos/org/repo/webhooks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"url": "https://example.com/webhook",
"content_type": "json",
"secret": "your-webhook-secret",
"events": ["push", "pull_request"]
}'Payload Format
Push Event
json
{
"event": "push",
"repository": {
"name": "my-repo",
"full_name": "org/my-repo",
"url": "https://kizuna.example.com/org/my-repo"
},
"ref": "refs/heads/main",
"before": "abc123...",
"after": "def456...",
"commits": [
{
"id": "def456...",
"message": "Fix authentication",
"author": {
"name": "Alice",
"email": "[email protected]"
}
}
],
"sender": {
"login": "alice",
"type": "User"
}
}Pull Request Event
json
{
"event": "pull_request",
"action": "opened",
"number": 42,
"pull_request": {
"title": "Add OAuth support",
"body": "Implements OAuth2...",
"state": "open",
"head": {
"ref": "feature/oauth",
"sha": "abc123..."
},
"base": {
"ref": "main",
"sha": "def456..."
}
},
"repository": { ... },
"sender": { ... }
}Securing Webhooks
HMAC Verification
Kizuna signs payloads with your secret:
X-Kizuna-Signature: sha256=abc123...Verify in your endpoint:
python
import hmac
import hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)IP Allowlisting
Webhook requests come from:
203.0.113.0/24
198.51.100.0/24Allow only these IPs in your firewall.
Delivery
Retry Logic
Kizuna retries failed deliveries:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
Delivery Status
View in Settings → Webhooks:
Webhook: https://example.com/webhook
├── Deliveries: 1,247
├── Successful: 1,245
└── Failed: 2
Recent Deliveries:
├── 2026-03-10 09:00:00 ✓ Success
├── 2026-03-10 08:55:00 ✓ Success
└── 2026-03-10 08:50:00 ✗ Failed (500)Redeliver
Manually retry failed deliveries:
bash
curl -X POST /api/v1/webhooks/123/deliveries/456/retry \
-H "Authorization: Bearer $TOKEN"Example Integrations
Slack Notifications
javascript
// Webhook endpoint
app.post('/webhook', (req, res) => {
const { event, pull_request } = req.body;
if (event === 'pull_request' && req.body.action === 'opened') {
slack.send({
channel: '#dev',
text: `New PR: ${pull_request.title}`
});
}
res.sendStatus(200);
});Deploy on Merge
python
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.json
if data['event'] == 'pull_request':
if data['action'] == 'closed' and data['pull_request']['merged']:
deploy_to_production()
return '', 200Update External Systems
javascript
app.post('/webhook', async (req, res) => {
const { event, issue } = req.body;
if (event === 'issue') {
await jira.syncIssue({
key: issue.number,
title: issue.title,
status: issue.state
});
}
res.sendStatus(200);
});Testing Webhooks
Ping Event
Test webhook without real events:
bash
curl -X POST /api/v1/webhooks/123/ping \
-H "Authorization: Bearer $TOKEN"Local Testing
Use ngrok for local development:
bash
# Start ngrok
ngrok http 3000
# Use ngrok URL as webhook URL
# https://abc123.ngrok.io/webhookManaging Webhooks
List Webhooks
bash
curl /api/v1/repos/org/repo/webhooksUpdate Webhook
bash
curl -X PATCH /api/v1/repos/org/repo/webhooks/123 \
-d '{"events": ["push", "pull_request", "release"]}'Delete Webhook
bash
curl -X DELETE /api/v1/repos/org/repo/webhooks/123Summary
Webhooks enable:
- Real-time integration — React to events instantly
- External automation — Trigger outside systems
- Notifications — Slack, email, etc.
- Custom workflows — Build your own logic
They're the bridge between Kizuna and your external tools.