Skip to main content
Code Storage provides a webhook system that allows you to receive real-time notifications about Git events across your storage layer. This enables you to integrate Code Storage deeply within your product, CI/CD pipelines, monitoring systems, and more.

How webhooks work

Webhooks are HTTP POST requests sent to your specified endpoint whenever certain events occur in your repositories. When you create a webhook subscription, Code Storage will:
  1. Monitor Events: Watch for the events you’ve subscribed to (e.g., push or repo.sync.* events)
  2. Generate Payloads: Create JSON payloads containing event details
  3. Sign Requests: Add cryptographic signatures for security verification
  4. Deliver Webhooks: Send HTTP POST requests to your endpoint with automatic retries

Webhook headers

Every webhook request includes the following headers:
  • Content-Type: application/json
  • User-Agent: Pierre-Webhook/1.0
  • X-Pierre-Event: <event_type> (e.g., push, repo.sync.started, repo.sync.succeeded, repo.sync.failed)
  • X-Pierre-Signature: t=1642678200,sha256=abc123... (security signature)

Custom headers

Add static headers in the webhook editor to authenticate requests or attach routing metadata, for example Authorization: Bearer <token> or X-Environment: production.
  • Each subscription supports up to 10 custom headers, with 8 KiB total across names, values, and the : and line-ending separators (4 bytes per header).
  • Custom headers require an HTTPS endpoint.
  • Names may contain ASCII letters, digits, and hyphens. Names are case-insensitive and must be unique. Values must contain printable ASCII characters, without leading or trailing whitespace.
  • Values are encrypted when stored. After saving, only names are returned; use Replace value to enter a new value, Save value to keep that edit in the form, Cancel to keep the saved value, or Remove header to delete the header. Save the webhook to apply the changes.
  • Changing the webhook URL preserves its saved headers.
  • If saved headers cannot be read, the editor shows a warning. You can still disable or delete the webhook, or clear or replace its saved headers. Other webhook settings preserve the saved values.
You cannot set reserved headers:
  • Pierre’s own headers: X-Pierre* and X-Git3P*.
  • Connection and framing headers: Host, User-Agent, Content-*, Connection, Keep-Alive, Transfer-Encoding, TE, Trailer, Upgrade, Expect, Accept-Encoding, HTTP2-Settings, and Proxy-*.
  • Client identity headers added by proxies and CDNs: Forwarded, Via, X-Forwarded-*, X-Envoy-*, X-Real-IP, X-Client-IP, True-Client-IP, X-Cluster-Client-IP, CF-Connecting-IP, CF-Connecting-IPv6, CF-Ray, Fastly-Client-IP, and CDN-Loop.
  • Trace propagation headers: Traceparent*, Tracestate*, Traceresponse*, Baggage*, X-Cloud-Trace-Context, X-Amzn-Trace-Id, and X-Amz-Cf-Id.
  • gRPC headers: Grpc-*.
Each delivery captures the subscription configuration before its first attempt. Changes to the URL, headers, or enabled state affect deliveries that capture their configuration after the change; existing deliveries, including retries, keep their original configuration. An event queued before an edit can use the new configuration if its delivery has not captured a snapshot yet. Custom headers do not change signature verification: the signature covers the timestamp and request body. Endpoint response bodies continue to appear in delivery history.

Event types

Common fields

Use these fields to identify the event, repository, and organization:

push

Triggered when commits are pushed to a repository.

repo.sync.started

Triggered when a repository sync run begins, before the upstream fetch executes. Useful for tracking sync progress or updating status indicators in your UI.

repo.sync.succeeded

Triggered when a sync run completes successfully.

repo.sync.failed

Triggered when a sync run fails, including mirror activity failures (after retries are exhausted) and infrastructure-level failures.

Sync event fields

Cancellations triggered internally (e.g., when a repository is detached from its upstream) do not produce a repo.sync.failed event.

Securing webhooks

To ensure the webhooks you receive are legitimate and from Code Storage, you must verify the HMAC signature included with each webhook delivery.

HMAC Signature Verification

Each webhook includes an X-Pierre-Signature header with the format:
The signature is computed as:

Webhook SDK methods

The SDK provides a helper function to verify webhook events quickly: verifyWebhook in TypeScript, verify_webhook in Python, and webhooks.VerifyWebhook in Go. It checks the signature and the timestamp, then returns the event with its type.

Advanced SDK usage

Custom Validation Options:
Unknown event types: for an event type that this SDK version does not know, such as a type from a newer API version, the SDK returns the type that Pierre sent and the payload:

Common verification errors

When the check fails, the SDK raises WebhookVerificationError. In Go, webhooks.VerifyWebhook returns a *pierre.WebhookVerificationError. Its reason field (Reason in Go) names the failure:
  • Missing signature components: malformed_signature
  • Timestamp too old: timestamp_out_of_range
  • Future timestamp: timestamp_out_of_range
  • Signature mismatch: signature_mismatch
  • Invalid JSON: invalid_payload (also for a payload with no event type)
  • Missing headers: missing_signature (no X-Pierre-Signature header)
A bad call, such as an empty secret, raises a PierreError with no reason (*pierre.PierreError in Go). Error Handling Best Practices: