Payload Transforms

Payload transforms let you reshape the outbound JSON body without changing the original accepted source payload. This is the right layer when the producer format is fixed but the consumer wants a narrower or cleaner JSON contract.

Transform model

Hooksbase supports one saved transform per webhook:

  • jsonpath with an expression
  • handlebars with a JSON-rendering template

Non-null transforms require Starter+.

This surface is intentionally constrained:

  • JSON input only
  • JSON output only
  • no JavaScript execution
  • no multi-step pipelines
  • no request method, URL, or header mutation

Auth model

  • Name
    Public API
    Type
    project API key
    Description

    Use GET/PUT /v1/webhooks/{id}/transform to inspect, replace, or clear the saved transform.

  • Name
    Dashboard
    Type
    session auth
    Description

    The dashboard lets you author, preview, and save a transform from the webhook's transform tab.

  • Name
    SDK / CLI
    Description

    The first-party SDK and CLI do not wrap transform management yet. Use raw HTTP.

JSONPath and Handlebars

JSONPath is the lighter option when you only need to extract or project part of the source payload. The expression is evaluated against the parsed source JSON; the result is serialized back out as the outbound body.

Handlebars is the better fit when you need to build a new JSON object from scratch. The template context exposed to the template is:

  • payload — the parsed JSON body
  • headers — the inbound headers (lower-cased)
  • contentType — the inbound Content-Type

The only helper available today is json, which lets you embed objects and arrays without string escaping. The rendered output must parse as JSON, or the transform returns 422.

Save a Handlebars transform

curl https://api.hooksbase.com/v1/webhooks/wh_123/transform \
  -X PUT \
  -H "Authorization: Bearer swk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "transform": {
      "kind": "handlebars",
      "template": "{\"tenant\":\"{{headers.x-tenant}}\",\"customer\":{{json payload.customer}}}"
    }
  }'

Clearing with { "transform": null } is allowed on every tier.

Execution and replay behavior

Execution order matters:

  1. ingest validation
  2. routing on the original source payload
  3. transform execution
  4. source payload storage
  5. transformed dispatch snapshot storage
  6. delivery persistence

Operational consequences:

  • non-JSON input, invalid JSON input, JSONPath evaluation failures, or Handlebars output that does not parse as JSON return 422
  • downgraded projects with a still-saved transform return 403 until the transform is cleared or the project is upgraded
  • retries, replay, DLQ re-drive, and bulk replay use the saved transformed dispatch snapshot when present, so replay stays deterministic after config changes
  • GET /v1/webhooks/{id}/transform
  • PUT /v1/webhooks/{id}/transform

Common mistakes

  • Expecting routing to see the transformed payload. Routing always evaluates the original source payload.
  • Returning non-JSON output from a Handlebars template.
  • Treating transforms as a free-tier feature. Non-null saves start at Starter.
  • Assuming replay will re-run the current transform instead of using the saved dispatch snapshot.

Was this page helpful?