Reform · AsyncAPI Specification

Reform Webhooks

Version

View Spec View on GitHub FormsForm BuilderLead GenerationHeadless FormsWebhookNo-CodeIntegrationCRMConversion Rate OptimizationEmbeddable ComponentsAsyncAPIWebhooksEvents

AsyncAPI Specification

reform-webhooks.yml Raw ↑
generated: '2026-08-14'
method: searched
source: https://docs.reform.app/article/7-webhooks
docs:
  - https://docs.reform.app/article/7-webhooks
  - https://www.reform.app/integrations/webhooks
api: Reform Forms
summary: >-
  Webhooks are the only server-to-server surface Reform publishes. Reform does
  not ship a public REST API, an OpenAPI definition, or an AsyncAPI document —
  webhooks are configured per form inside the dashboard (Integrations → Webhook)
  and Reform POSTs a signed JSON event to each active destination URL. This file
  is the webhook catalogue derived verbatim from Reform's own documentation; it
  is NOT an AsyncAPI document and no AsyncAPI pointer is emitted, because Reform
  publishes none.
asyncapi_published: false
availability:
  plan: Pro
  note: >-
    Reform's pricing page lists "Webhooks for custom integrations" as a Pro-plan
    feature. Free and Basic plans cannot configure webhook destinations.
configuration:
  where: Reform dashboard → form → Integrations → Webhook integration
  model: >-
    Toggle the webhook integration on and paste the destination URL. Multiple
    destinations are supported; Reform sends to every URL in the "Active
    webhooks" list.
  secret_retrieval: >-
    Each webhook has its own secret. Open the dashboard → form → Integrations →
    Webhook integration settings → locate the webhook → click the lock icon.
delivery:
  transport: https-post
  content_type: application/json
  signature:
    algorithm: HMAC-SHA256
    header: Signature
    format: hex digest of the raw request body, keyed with the per-webhook secret
    secret_scope: per webhook destination
    verification: >-
      Read the Signature header, read the request body, compute an HMAC-SHA256
      of the body using the webhook secret, and compare it to the header value.
      Reform documents a PHP reference implementation using hash_hmac('sha256',
      $body, $secret).
    docs: https://docs.reform.app/article/7-webhooks
  retries:
    documented: false
    note: >-
      Reform does not publish a retry schedule, a delivery-failure policy, or a
      timeout. The marketing page claims "robust error handling"; no mechanics
      are documented.
  ordering:
    documented: false
  deduplication:
    field: id
    note: >-
      Every event carries a UUID `id`. Reform does not document at-least-once vs
      exactly-once delivery, so consumers should treat `id` as the dedup key.
      Reform's own guidance elsewhere recommends idempotent handlers.
envelope:
  fields:
    - {name: type, type: string, description: The event type, e.g. form.submitted.}
    - {name: id, type: string (uuid), description: Unique identifier for this event delivery.}
    - {name: occurred_at, type: string (ISO 8601 with offset), description: When the event happened, e.g. '2021-05-25T04:56:26+00:00'.}
    - {name: payload, type: object, description: Event-specific body; for form.submitted it carries `form` and `submission`.}
events:
  - name: form.submitted
    description: >-
      Fires every time someone submits a form. The payload carries the form the
      submission belongs to and the submission itself, including every answer.
    payload:
      form:
        - {name: id, type: string (uuid), description: The form's unique identifier.}
        - {name: created_at, type: string (ISO 8601), description: When the form was created.}
        - {name: name, type: string, description: The form's name in the builder.}
        - {name: status, type: string, description: 'Form status, e.g. published. (Present in the PHP signature example.)'}
        - {name: link, type: string (url), description: 'Public hosted-form URL, e.g. https://forms.reform.app/W8eMHb/zUC012.'}
      submission:
        - {name: id, type: string (uuid), description: The submission's unique identifier.}
        - {name: created_at, type: string (ISO 8601), description: When the submission was recorded.}
        - name: answers
          type: object
          description: >-
            A map keyed by BLOCK id (the question's unique id in the builder),
            not by position. Reform documents this explicitly so consumers do not
            depend on question order. Each value is an object of
            {id, question, answer} where `id` is the answer's own uuid.
    example_shape: |
      {
        "type": "form.submitted",
        "id": "<event-uuid>",
        "occurred_at": "2021-05-25T04:56:26+00:00",
        "payload": {
          "form": {
            "id": "<form-uuid>",
            "created_at": "2021-05-25T04:53:12+00:00",
            "name": "Breakfast survey",
            "link": "https://forms.reform.app/W8eMHb/zUC012"
          },
          "submission": {
            "id": "<submission-uuid>",
            "created_at": "2021-05-25T04:56:26+00:00",
            "answers": {
              "<block-uuid>": {
                "id": "<answer-uuid>",
                "question": "What's your name?",
                "answer": "..."
              }
            }
          }
        }
      }
event_count: 1
gaps:
  - >-
    Only one event type (form.submitted) is documented. The marketing page for
    the webhooks integration advertises "Custom Event Triggers ... such as
    submissions, updates, or even conditional triggers"; the documentation names
    no event other than form.submitted.
  - >-
    No JSON Schema, OpenAPI `webhooks:` block, or AsyncAPI document is published
    for the payload — the only machine-readable artefact is the example body in
    the help-centre article.
  - No published retry, backoff, timeout, or replay/redelivery policy.