Skip to main content
BunShip includes a complete outbound webhook system. Your users can register HTTPS endpoints and receive POST requests whenever events occur in their organization — new members joining, billing changes, API key creation, and any custom events you define.

Creating Webhook Endpoints

Each organization can register multiple webhook endpoints. When creating an endpoint, BunShip generates a unique signing secret:
API call:
The response includes the secret field. This is the only time the full secret is returned — store it securely on your receiving server.
If events is an empty array, the endpoint receives all event types. Specify events explicitly to reduce noise.

Event Types and Payloads

BunShip dispatches events as JSON POST requests. Every payload follows this structure:
Common event types include: You can add custom event types by dispatching them through the webhook service.

Signature Verification

Every webhook delivery is signed with HMAC-SHA256. The signature is sent in the X-Webhook-Signature header using a timestamp-prefixed format that prevents replay attacks:

How signing works

BunShip creates the signature by concatenating a Unix timestamp with the raw JSON payload, then computing an HMAC-SHA256 hash using the endpoint’s secret:

Verifying on your server

To verify a webhook on your receiving server:
1

Extract the timestamp and signature

Parse the X-Webhook-Signature header to get the t (timestamp) and v1 (signature) values.
2

Check the timestamp

Reject requests where the timestamp is more than 5 minutes old to prevent replay attacks.
3

Compute the expected signature

Recreate the signed payload (timestamp.body) and compute HMAC-SHA256 with your webhook secret.
4

Compare signatures

Use a constant-time comparison to prevent timing attacks:

Verification example (Node.js / Bun)

Retry Logic

Failed deliveries are retried up to 3 attempts with increasing delays: A delivery is considered failed if the receiving server returns a non-2xx status code or the request times out (30 seconds). After all retries are exhausted, the delivery is marked as permanently failed.
The webhook worker uses BullMQ with exponential backoff for queue-based retries:

Delivery Tracking and Debugging

Every dispatch creates a webhookDeliveries record that tracks:
  • Event type — Which event triggered the delivery
  • Payload — The full JSON body sent
  • Status code — HTTP response code from the receiving server
  • Response — First 500 characters of the response body
  • Attempts — Number of delivery attempts made
  • Delivered at — Timestamp of successful delivery (null if still pending)
  • Next retry at — When the next retry is scheduled
Retrieve delivery history for a specific endpoint:

Sending a test event

Verify your endpoint is working by sending a test event:
This dispatches a test event with a sample payload:

Delivery Headers

Each webhook request includes these headers:

Secret Rotation

Rotate a webhook’s signing secret without deleting and recreating the endpoint:
The new secret is returned in the response. Update your receiving server immediately — deliveries signed with the old secret will fail verification.

SSRF Protection

BunShip validates webhook URLs to prevent Server-Side Request Forgery (SSRF). The following are blocked:
  • Private IP ranges127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 169.254.x.x
  • Localhostlocalhost, 127.0.0.1, 0.0.0.0, ::1
  • Internal hostnames — Hostnames without a dot (e.g., redis, postgres)
  • Non-HTTP protocols — Only http:// and https:// are allowed
Validation runs on both endpoint creation and update. Attempts to register blocked URLs return a 400 Validation Error.

Plan Limits

Webhook endpoint counts are enforced per plan: