Setting up a Webhook Surface

Set up a Webhook Surface that receives HTTP events, verifies provider signatures, routes events to Capabilities, and passes payload data to a Flow or Agent.

Before you begin

Create a Product with at least one Capability. Get access to the external provider’s webhook settings so you can register the Webhook URL and configure signature verification.

Create a Webhook Surface

To create a Webhook Surface, follow these steps:

  1. Open the Product that receives the events.
  2. On the Product page, click Surfaces, then click Add Surface.
  3. Select Webhook.
  4. Enter a name for the Surface.
  5. Copy the Webhook URL.
  6. Register the URL in the external provider’s webhook settings.

Provide a payload shape

A Webhook Surface uses a schema to route events and map payload fields. Choose one of these options:

  • Use a sample: paste a JSON payload, JSON Schema, or AsyncAPI document. Runtype infers a schema from the sample.
  • Use listening mode: turn on listening mode and send test events from the external provider. After three observations, Runtype proposes a schema that marks fields as required or optional.

The Webhook Surface uses these states during setup:

  • Draft: the Surface exists without observations.
  • Listening: the Surface collects test events for schema inference.
  • Schema proposed: the Surface has enough observations for a proposed schema.
  • Active: you confirmed the schema, and the Surface processes incoming events.
  • Drift detected: an incoming payload exceeds the configured difference threshold from the confirmed schema.

When the Surface reaches Schema proposed, review the proposed schema and click Confirm. To start over, click Clear to remove the observations, then send another set of test events.

Verify webhook signatures

In Signature Verification, select the provider and configure the credential that it uses to sign requests. Runtype rejects requests when configured signature verification fails.

The supported providers use these signature headers:

  • Standard Webhooks: webhook-signature.
  • Stripe: stripe-signature.
  • GitHub: x-hub-signature-256.
  • Shopify: x-shopify-hmac-sha256.
  • Twilio: x-twilio-signature.
  • SendGrid: x-twilio-email-event-webhook-signature.
  • Slack: x-slack-signature.
  • Custom HMAC-SHA256 and Custom HMAC-SHA1: a configurable signature header.

Some providers include a timestamp for replay protection. Signature comparison uses constant-time checks. Select No verification for an internal source that does not sign requests.

Route events to Capabilities

Use event routing when one Webhook Surface receives multiple event types. To configure event routing, follow these steps:

  1. Set Event Type Path to the dot path of the field that names the event, such as type for Stripe.
  2. Add a route for each event pattern and select its Capability. A pattern such as payment_intent.* matches a family of event types.
  3. Optional: select a fallback Capability for events that match no route.

Map payload fields to Flow inputs

Runtype passes the complete request body to the Capability as {{payload}}. You can reference nested fields with a dot path, such as {{payload.data.object.amount}}.

By default, Runtype also exposes top-level payload fields as Flow inputs with the same names. For example, {{customerId}} resolves when the payload has a customerId field. Runtype omits top-level fields that start with _ because that prefix is reserved.

To map nested or differently named fields, use the Flow input name as the key and the dot path into the payload as the value. This example maps two nested fields:

Field mapping examples
1amount: data.object.amount
2customerId: data.object.customer

When you enter a source path, the editor suggests paths from the confirmed schema.

Choose synchronous or asynchronous handling

Choose a response mode that matches the provider’s requirements:

  • Async: Runtype durably stores the execution job before acknowledging the event, then runs the Capability independently of the HTTP request. Use this mode when the provider does not need the execution result.
  • Synchronous: the caller waits for the Capability to finish and receives its result. Use this mode when the provider expects the execution result in the response.

Some providers inspect the response body instead of the status code. Select Custom response to return fixed content. For example, return an empty Twilio Markup Language (TwiML) document with an application/xml content type for Twilio. You can also return status 204 with no content for Shopify. A custom response runs the Capability asynchronously.

An asynchronous acknowledgment confirms acceptance, not successful execution. Runtype returns 202 for a newly accepted event and 200 for a duplicate, unless you configured a custom response. Keep the provider event ID unchanged when retrying a delivery. Without an event ID, Runtype uses the raw request body to identify duplicates. Duplicate suppression lasts 24 hours from acceptance.

For async deliveries, Runtype checks x-github-delivery, x-shopify-webhook-id, and webhook-id in that order, then body id and event_id. A delivery header takes precedence over a resource ID in the body.

For repeated logical events with identical payloads, send a different webhook-id header for each event. Reuse that ID only for retries of the same event. This is required for scheduled integrations that repeatedly send the same body without a provider event ID.

If durable storage or handoff fails, Runtype returns 500 or 503 instead of a success acknowledgment, including for custom responses. Configure the provider to retry these errors. Asynchronous execution jobs have an 8 MiB serialized limit, including the payload, mapped inputs, and execution configuration. A smaller HTTP request can exceed this limit when its data appears in multiple inputs. Runtype returns 413 for jobs that exceed the limit; reduce the payload before retrying.

Test the connection

To verify the connection, follow these steps:

  1. Send a test event from the external provider.
  2. If the Surface is Listening, send two more test events so it can propose a schema after three observations.
  3. When the Surface reaches Schema proposed, review the schema and click Confirm.
  4. Send another test event.
  5. Confirm that the event reaches the Product and routes to the expected Capability.
  6. In What are Logs?, inspect the execution and the payload that the Flow received.

If an incoming payload differs from the confirmed schema enough to exceed the configured threshold, the Surface enters Drift detected. Review the proposed schema and confirm it before you continue processing that payload shape.

Troubleshoot webhook setup

Use these checks when a Webhook Surface does not process an event:

  • Invalid signature: verify the selected provider, credential, and signature header. Runtype rejects the request before it runs the Capability.
  • The Surface stays in Listening: send three test events with object payloads and confirm that they reach the Webhook URL.
  • Unexpected routing: verify Event Type Path, route patterns, and the fallback Capability. An event that matches no route uses the fallback when you configure one.

Next steps

Continue with these guides: