Events and webhooks

Shaperail has a built-in event system that emits events on every data mutation, routes them to configurable targets, and delivers outbound webhooks with HMAC-SHA256 signatures. It also accepts inbound webhooks from external services.

All event processing is non-blocking. Events are enqueued as background jobs and never delay the HTTP response to your client.

Auto-emitted events

Every generated endpoint that creates, updates, or deletes a record automatically emits an event named <resource>.<action>:

Endpoint action Event name
create users.created
update users.updated
delete users.deleted

The event payload contains the resource name, action, full record data, a unique event_id, and an ISO 8601 timestamp.

Custom events

Add the events: key to any endpoint definition to emit additional events:

endpoints:
  create:
    method: POST
    path: /users
    auth: [admin]
    input: [email, name, role, org_id]
    events: [user.created]
    jobs: [send_welcome_email]

Custom event names follow the same <resource>.<action> convention but you choose the name.

Event subscribers

In shaperail.config.yaml, the events.subscribers list maps event patterns to one or more targets. Each subscriber has an event pattern and a list of targets.

events:
  subscribers:
    - event: "users.created"
      targets:
        - type: job
          name: send_welcome_email
        - type: webhook
          url: "https://example.com/hooks/user-created"
        - type: channel
          name: notifications
          room: "org:{org_id}"
        - type: hook
          name: validate_org

    - event: "*.deleted"
      targets:
        - type: job
          name: cleanup_job

Event patterns

Subscribers match events using these patterns:

Pattern Matches
users.created Exact match only
users.* Any event on the users resource
*.created Any resource’s created event
* Every event

Target types

Type Key fields Behavior
job name Enqueues a background job by name
webhook url POSTs the event payload to an external URL
channel name, room Broadcasts to a WebSocket channel and room
hook name Executes a named hook function

Outbound webhooks

When a subscriber target has type: webhook, Shaperail delivers the event payload as an HTTP POST to the specified URL.

Signing

Every outbound request includes an X-Shaperail-Signature header:

X-Shaperail-Signature: sha256=<hex-encoded HMAC-SHA256 digest>

The digest is computed over the raw JSON request body using the secret from the environment variable specified in events.webhooks.secret_env.

To verify on the receiving end, compute HMAC-SHA256 over the raw body with your shared secret and compare the hex digest (use constant-time comparison).

Webhook configuration

events:
  webhooks:
    secret_env: WEBHOOK_SECRET   # env var holding the signing secret
    timeout_secs: 30             # HTTP timeout per delivery attempt
    max_retries: 3               # retry attempts on failure

All three fields have defaults (WEBHOOK_SECRET, 30, 3) so the entire webhooks: block is optional if the defaults work for you.

Retry behavior

Failed deliveries (non-2xx status or connection error) are retried up to max_retries times with exponential backoff. Retries are managed through the job queue, so they survive server restarts.

Webhook delivery log

Every delivery attempt is recorded in the shaperail_webhook_delivery_log table with:

Column Description
delivery_id Unique ID for this attempt
event_id The event that triggered delivery
url Target webhook URL
status_code HTTP status (0 if connection failed)
status success, failed, or pending
latency_ms Response time in milliseconds
error Error message if delivery failed
attempt Attempt number (1, 2, 3, …)
timestamp ISO 8601 timestamp

Query delivery history for a specific event or list recent deliveries for debugging.

Inbound webhooks

Shaperail can receive webhooks from external services, verify their signatures, and re-emit the payload as internal events.

Configuration

events:
  inbound:
    - path: /webhooks/stripe
      secret_env: STRIPE_WEBHOOK_SECRET
      events: ["payment.completed", "subscription.updated"]

    - path: /webhooks/github
      secret_env: GITHUB_WEBHOOK_SECRET
      events: []   # empty = accept all event types

Each entry registers a POST endpoint at the specified path. The secret_env field names the environment variable holding the verification secret.

The events list filters which event types are accepted. An empty list accepts all events.

Signature verification

Inbound verification supports three header formats automatically:

Service Header Format
Shaperail X-Shaperail-Signature sha256=<hex>
GitHub X-Hub-Signature-256 sha256=<hex>
Stripe Stripe-Signature t=<timestamp>,v1=<signature>

The handler checks headers in this order and uses the first one found. Stripe signatures are verified by computing HMAC-SHA256 over <timestamp>.<body>.

Requests with invalid or missing signatures return 401 Unauthorized.

Internal re-emission

Accepted inbound payloads are re-emitted as internal events named inbound.<event_type>, where the event type is extracted from the type, event, or action field in the request body. These events flow through the same subscriber system as any other event.

Event log

All emitted events are written to the shaperail_event_log table. This is an append-only audit trail – records are never updated or deleted.

Column Description
event_id Unique event ID
event Event name (e.g., users.created)
resource Resource name
action Action that triggered the event
data Full record payload (JSONB)
timestamp ISO 8601 timestamp

The event log is written via the job queue, so it is also non-blocking.

Full configuration example

events:
  subscribers:
    - event: "users.created"
      targets:
        - type: job
          name: send_welcome_email
        - type: webhook
          url: "https://hooks.example.com/new-user"
        - type: channel
          name: notifications
          room: "org:{org_id}"

    - event: "orders.*"
      targets:
        - type: hook
          name: recalculate_totals

    - event: "*"
      targets:
        - type: job
          name: audit_logger

  webhooks:
    secret_env: WEBHOOK_SECRET
    timeout_secs: 30
    max_retries: 3

  inbound:
    - path: /webhooks/stripe
      secret_env: STRIPE_WEBHOOK_SECRET
      events: ["payment.completed", "subscription.updated"]
    - path: /webhooks/github
      secret_env: GITHUB_WEBHOOK_SECRET
      events: []

Back to top

Shaperail documentation lives in the same repository as the framework so every release has versioned instructions.

This site uses Just the Docs, a documentation theme for Jekyll.