Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kiwifs.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let you push change events to external services whenever pages are created, updated, or deleted. Each webhook receives a signed HTTP POST with details about the change.

Enabling webhooks

Add the [webhooks] section to your .kiwi/config.toml:
[webhooks]
enabled = true
max_workers = 4
max_retries = 3
KeyDefaultDescription
enabledfalseEnable the webhook subsystem.
max_workers4Concurrent dispatch goroutines.
max_retries3Retries on delivery failure.

Creating a webhook

Register a webhook URL with an optional glob pattern to filter which paths trigger it.
curl -X POST 'http://localhost:3333/api/kiwi/webhooks' \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/hook", "path_glob": "concepts/**"}'
{
  "id": "wh_abc123",
  "url": "https://example.com/hook",
  "path_glob": "concepts/**",
  "secret": "whsec_k9x2m...",
  "created_at": "2026-05-04T12:00:00Z",
  "enabled": true
}
The secret is only returned once at creation time. Store it securely — you’ll need it to verify webhook signatures.

Path glob patterns

PatternMatches
**All files (default)
concepts/**All files under concepts/
reports/*.mdMarkdown files directly in reports/
Glob matching uses Go’s filepath.Match with an added ** recursive wildcard.

Payload format

Every webhook receives a JSON POST body:
{
  "type": "write",
  "path": "concepts/auth.md",
  "actor": "agent:docs-writer",
  "timestamp": "2026-05-04T12:05:00Z"
}
FieldDescription
typeEvent type: write, delete, bulk, import.
pathFile path that changed.
actorThe X-Actor header from the originating request.
timestampISO 8601 timestamp of the change.

Signature verification

Every webhook POST includes three headers for verification:
HeaderDescription
webhook-idUnique message ID for deduplication.
webhook-timestampUnix timestamp of the dispatch.
webhook-signaturev1,<base64> HMAC-SHA256 signature.
The signature is computed over {webhook-id}.{webhook-timestamp}.{body} using the webhook secret as the HMAC key.
import hmac, hashlib, base64

def verify(secret, msg_id, timestamp, body, signature):
    signed_content = f"{msg_id}.{timestamp}.{body}"
    expected = hmac.new(
        base64.b64decode(secret),
        signed_content.encode(),
        hashlib.sha256
    ).digest()
    return hmac.compare_digest(
        base64.b64encode(expected).decode(),
        signature.removeprefix("v1,")
    )

Managing webhooks

List all webhooks

curl 'http://localhost:3333/api/kiwi/webhooks'
The secret field is omitted from list responses for security.

Delete a webhook

curl -X DELETE 'http://localhost:3333/api/kiwi/webhooks/wh_abc123'
Last modified on May 4, 2026