Skip to content

Webhooks

Webhooks are account-level. One URL receives git events from every repository you own. Amendable stores Git. Your endpoint runs CI, CAD export, notifications, or whatever your product does next.

git push to Amendable to your HTTPS URL, verified with HMAC, reply 204.
EventWhen
pushA branch or tag tip moved, including the first commit on a new ref
createA branch or tag was created (before is 40 zeros)
deleteA branch or tag was deleted (after is 40 zeros)
pingSynthetic. Use Ping or POST /v1/webhooks/{id}/ping
repositoryReserved. Do not rely on it yet

Creating a branch emits create and push.

The signing secret is generated by Amendable. You cannot set it. It is returned once on create.

Terminal window
amendable webhook create https://ci.example.com/hooks/amendable \
--events push,create,delete,ping

Save the printed secret.

Terminal window
amendable webhook ping 22222222-2222-2222-2222-222222222222
amendable webhook deliveries 22222222-2222-2222-2222-222222222222 --include-payload --json

Every delivery includes:

HeaderValue
Content-Typeapplication/json
X-Amendable-Eventpush, create, delete, or ping
X-Amendable-Event-IdEvent UUID
X-Amendable-DeliveryDelivery UUID
X-Amendable-SignatureHex HMAC-SHA256 of the raw body using the webhook secret

The examples in this repo are tested.

import hashlib
import hmac
def valid(secret: str, body: bytes, signature: str) -> bool:
expected = hmac.new(secret.encode("utf-8"), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

Run the checked-in verifier:

Terminal window
python examples/webhook/verify.py \
--secret "$AMENDABLE_WEBHOOK_SECRET" \
--signature "$HTTP_X_AMENDABLE_SIGNATURE" \
--body-file payload.json

A stdlib receiver is in examples/webhook/receiver.py. It returns 204 after a valid signature.

Enough to clone and check out after:

{
"id": "event-uuid",
"type": "push",
"ref": "refs/heads/main",
"ref_name": "main",
"ref_type": "branch",
"before": "0000000000000000000000000000000000000000",
"after": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"created": true,
"deleted": false,
"commits": [],
"head_commit": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" },
"tag": null,
"repository": {
"id": "repo-uuid",
"name": "my-repo",
"full_name": "demo/my-repo",
"default_branch": "main",
"html_url": "https://amendable.io/r/demo/my-repo",
"clone_url": "https://amendable.io/r/demo/my-repo.git",
"owner": { "id": "user-uuid", "username": "demo" }
}
}

Full field list: Webhook payloads.

  • Timeout: 30 seconds
  • Your endpoint should return 2xx quickly and do work asynchronously
  • Failed deliveries are visible in the UI and GET /v1/webhooks/{id}/deliveries

Ping even if ping is not in events. The ping endpoint force-delivers to that webhook only.