> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opnform.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Webhook Integration

> Create a new generic webhook or provider-specific Make integration for a form. Requires `manage-integrations` ability.

# Create Webhook Integration

Add a new webhook integration to send form submissions to an external endpoint.

## Authentication & Scope

This endpoint requires a **Personal Access Token** with the `manage-integrations` ability.

## Request

<ParamField path="form" type="number" required>
  The ID of the form to which the webhook will be added.
</ParamField>

<ParamField body="integration_id" type="string" required>
  Use `"webhook"` for a generic webhook integration or `"make"` for the
  official OpnForm app on Make. Both values are registered integration
  handlers exposed by this endpoint.
</ParamField>

<ParamField body="status" type="string" required>
  The initial status of the webhook. Allowed values: `"active"`, `"inactive"`.
</ParamField>

<ParamField body="data" type="object" required>
  Configuration object containing webhook details.

  <Expandable title="data properties">
    <ParamField body="webhook_url" type="string" required>
      The URL where form submissions will be sent. Must be a valid HTTPS URL that resolves only to public IP addresses. Private, loopback, link-local, and cloud metadata addresses are rejected.
    </ParamField>

    <ParamField body="webhook_secret" type="string">
      Optional signing secret for HMAC-SHA256 validation. When provided, webhook
      requests will include an `X-Webhook-Signature` header. Must be at least 12
      characters. Recommended for security. Should be a random, cryptographically
      secure string.
    </ParamField>

    <ParamField body="webhook_headers" type="object">
      Optional custom HTTP headers to send with each webhook request. Provided as key-value pairs where both keys and values are strings. Maximum 10 headers allowed, each value max 255 characters.

      **Blocked headers** (cannot be customized): `Authorization`, `X-Webhook-Signature`, `Content-Type`, `Host`, `Cookie`, `X-CSRF-Token`, `Content-Length`, and others reserved for security.

      Example:

      ```json theme={null}
      {
          "X-API-Key": "your-api-key",
          "X-Custom-ID": "custom-value"
      }
      ```
    </ParamField>

    <ParamField body="provider_url" type="string">
      Optional Make scenario URL. This property is accepted by the `"make"`
      integration and is ignored by generic webhook integrations.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="logic" type="object">
  Optional conditional logic to trigger the webhook only when specific
  conditions are met.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://api.opnform.com/open/forms/123/integrations' \
    -H 'Authorization: Bearer YOUR_PAT' \
    -H 'Content-Type: application/json' \
    -d '{
      "integration_id": "webhook",
      "status": "active",
      "data": {
        "webhook_url": "https://example.com/opnform-hook",
        "webhook_secret": "whsec_1234567890abcdefghijklmnop",
        "webhook_headers": {
          "X-API-Key": "my-api-key",
          "X-Custom-Header": "custom-value"
        }
      }
    }'
  ```
</RequestExample>

For the official OpnForm app on Make, the attach request uses the same endpoint
with the provider-specific integration identifier:

<RequestExample>
  ```bash cURL Make theme={null}
  curl -X POST 'https://api.opnform.com/open/forms/123/integrations' \
    -H 'Authorization: Bearer YOUR_PAT' \
    -H 'Content-Type: application/json' \
    -d '{
      "integration_id": "make",
      "status": "active",
      "logic": null,
      "data": {
        "webhook_url": "https://hook.eu1.make.com/example"
      }
    }'
  ```
</RequestExample>

## Response

`200 OK` – Webhook created successfully.

<ResponseExample>
  ```json Success theme={null}
  {
    "message": "Form Integration was created.",
    "form_integration": {
      "id": 42,
      "form_id": 123,
      "integration_id": "webhook",
      "status": "active",
      "data": {
        "webhook_url": "https://example.com/opnform-hook",
        "webhook_secret": "whsec_1234567890abcdefghijklmnop",
        "webhook_headers": {
          "X-API-Key": "my-api-key",
          "X-Custom-Header": "custom-value"
        }
      }
    }
  }
  ```
</ResponseExample>

`403 Forbidden` – The token does not have `manage-integrations` ability or insufficient form permissions.

`404 Not Found` – Form not found.

`422 Unprocessable Entity` – Validation error (e.g., invalid or non-public webhook URL, webhook\_secret too short, blocked header).

<ResponseExample>
  ```json Error theme={null}
  {
    "message": "The given data was invalid.",
    "errors": {
      "data.webhook_url": ["The webhook URL must use HTTPS."],
      "data.webhook_secret": ["The webhook secret must be at least 12 characters."],
      "data.webhook_headers": ["The 'Authorization' header cannot be customized for security reasons."]
    }
  }
  ```
</ResponseExample>

## Security

If you provide a `webhook_secret` when creating the webhook, OpnForm will sign each webhook request with an HMAC-SHA256 signature. This allows you to verify that the webhook came from OpnForm and hasn't been tampered with.

Webhook URLs are validated when they are saved and again before each delivery. OpnForm does not follow webhook redirects, and private network destinations are blocked unless the instance operator explicitly enables private webhook URLs for a self-hosted deployment.

Each webhook request will include:

* **`X-Webhook-Signature` header**: Contains the signature in format `sha256=HEXADECIMAL_VALUE`
* **Custom headers**: Any headers you specified in `webhook_headers` (except blocked headers)
* **JSON body metadata**: The payload includes `form_id` and `submission_id` so you can correlate webhook deliveries with OpnForm API submission management endpoints

### Blocked Headers

For security reasons, the following headers cannot be customized:

* `Authorization`
* `X-Webhook-Signature`
* `Content-Type`
* `Content-Length`
* `Host`
* `Cookie`
* `X-CSRF-Token`
* `X-Forwarded-For`
* `X-Forwarded-Proto`
* `X-Real-IP`

See [Validating Webhook Signatures](/api-reference/integrations/webhook-security) for implementation examples.

## Make payload

The `"make"` handler sends a provider-specific payload matching the output
interface of the OpnForm Make app:

```json theme={null}
{
  "form_id": 123,
  "form_title": "Contact Form",
  "form_slug": "contact-form",
  "submission_id": 456,
  "edit_link": "https://opnform.com/forms/contact-form?submission_id=example",
  "data": {
    "field-id": {
      "value": "Jane Doe",
      "name": "Name",
      "type": "text"
    }
  }
}
```

`edit_link` is present only when editable submissions are enabled. Unlike the
generic webhook payload, the Make payload omits the deprecated `submission` and
`message` properties.

<Warning>
  Do not commit webhook secrets to version control. Use environment variables
  or secure vaults to manage them.
</Warning>


## OpenAPI

````yaml post /open/forms/{form}/integrations
openapi: 3.0.1
info:
  title: OpnForm API
  description: API for interacting with OpnForm, primarily used for Zapier integration
  version: 1.0.0
servers:
  - url: https://api.opnform.com
security:
  - bearerAuth: []
tags:
  - name: Workspaces
    description: Create and manage workspaces.
  - name: Workspace Users
    description: Manage users within a workspace.
  - name: Forms
    description: Manage and retrieve forms.
  - name: Submissions
    description: Access and manage form submissions.
  - name: Integrations
    description: Manage form integrations (webhooks) via API.
  - name: Zapier
    description: Legacy endpoints for the Zapier integration.
paths:
  /open/forms/{form}/integrations:
    post:
      tags:
        - Integrations
      summary: Create Webhook Integration
      description: >-
        Create a new generic webhook or provider-specific Make integration for a
        form. Requires `manage-integrations` ability.
      parameters:
        - name: form
          in: path
          required: true
          schema:
            type: number
            description: The ID of the form.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - integration_id
                - data
              properties:
                integration_id:
                  type: string
                  enum:
                    - webhook
                    - make
                  description: >-
                    Use "webhook" for a generic webhook or "make" for the
                    official OpnForm app on Make
                status:
                  type: string
                  enum:
                    - active
                    - inactive
                  default: active
                  description: The initial status of the webhook
                data:
                  type: object
                  required:
                    - webhook_url
                  properties:
                    webhook_url:
                      type: string
                      format: uri
                      description: The URL where submissions will be sent
                    provider_url:
                      type: string
                      format: uri
                      nullable: true
                      description: >-
                        Optional Make scenario URL stored with a Make
                        integration
      responses:
        '200':
          description: Webhook created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Form Integration was created.
                  form_integration:
                    $ref: '#/components/schemas/FormIntegration'
        '403':
          description: Forbidden – insufficient permissions
        '404':
          description: Form not found
        '422':
          description: Validation error
      security:
        - bearerAuth: []
components:
  schemas:
    FormIntegration:
      type: object
      properties:
        id:
          type: number
          description: Unique identifier for the integration.
          readOnly: true
        form_id:
          type: number
          description: The ID of the associated form.
          readOnly: true
        integration_id:
          type: string
          description: >-
            Type of integration exposed via API, including "webhook" and the
            provider-specific "make" integration.
          example: webhook
        status:
          type: string
          enum:
            - active
            - inactive
          description: Whether the integration is active.
        data:
          type: object
          description: >-
            Integration-specific configuration. For webhooks, contains
            webhook_url.
          example:
            webhook_url: https://example.com/opnform-hook
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Personal Access Token
      x-bearer-scopemap:
        workspaces-read: Read access to workspaces
        workspaces-write: Write access to workspaces
        workspace-users-read: Read access to workspace users
        workspace-users-write: Write access to workspace users
        forms-read: Read access to forms
        forms-write: Write access to forms
        manage-integrations: Manage form integrations (webhooks)

````