Sevro

Webhooks

Receive webhooks from external services and trigger workflows with verified, signed payloads.

What are webhooks?

Webhooks let external services push data into Sevro. When a webhook fires, Sevro verifies the signature, parses the body, and triggers any workflow with a webhook trigger.

How webhooks work

  1. You create a workflow with a webhook trigger
  2. Sevro generates a unique webhook URL
  3. You configure the external service to POST to that URL
  4. When a payload arrives, Sevro verifies the HMAC-SHA256 signature and evaluates the transform expression
  5. The transformed data is passed to the workflow as input

Signature verification

Sevro checks the request signature using the webhook secret. It looks for the signature in these headers (in order):

HeaderFormat
X-Sevro-Signaturesha256=<hex>
X-Hub-Signature-256sha256=<hex>
X-Webhook-Signature<hex>

The signature is computed as HMAC-SHA256(body, webhook_secret). If the signature doesn't match, the request is rejected with 401 Unauthorized.

No Bearer token is required for webhook requests — authentication is via the webhook secret alone.

Transform expression

The transform is a CEL expression that maps the incoming JSON body to the workflow's input. The parsed JSON body is available as body:

trigger:
  type: webhook
  transform: |
    {
      "customer_email": body.customer.email,
      "amount": body.payment.amount,
      "invoice_id": body.payment.metadata.invoice_id
    }

The result of the transform is passed to the workflow as input.

Configuring a webhook

1. Create a workflow with a webhook trigger

name: billing
workflows:
  - ref: stripe-payment-received
    label: Stripe Payment Received
    trigger:
      type: webhook
      transform: |
        {
          "invoice_id": body.metadata.invoice_id,
          "amount": body.amount,
          "customer_email": body.receipt_email
        }
    nodes:
      - id: mark-paid
        type: method_call
        entity: invoice
        method: markPaid
        input: |
          {
            "record_id": input.invoice_id
          }

2. Apply the module

sevro module apply -f billing.yaml

3. Get the webhook URL

The webhook URL is returned when you apply the module, or you can retrieve it:

sevro workflow get \
  --module <module-id> \
  --workflow stripe-payment-received

The URL looks like:

https://your-sevro-instance/webhooks/<workflow-id>

4. Configure the external service

Point the external service (e.g. Stripe, GitHub, Shopify) at the webhook URL. Use the webhook secret as the signing key.

Testing webhooks

Test a webhook with curl:

# Generate the signature
SECRET="your-webhook-secret"
BODY='{"payment":{"amount":5000,"metadata":{"invoice_id":"abc-123"}}}'
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')

# Send the request
curl -X POST https://your-sevro-instance/webhooks/<workflow-id> \
  -H "Content-Type: application/json" \
  -H "X-Sevro-Signature: sha256=$SIGNATURE" \
  -d "$BODY"

Next steps

On this page