Webhooks

  • JNext lesson
  • KPrevious lesson
  • FSearch lessons
  • EscClear search

The Webhook action sends form submission data to an external URL via HTTP POST request. This is useful for connecting forms to third-party services, CRMs, Zapier, n8n, or any API that accepts incoming data.

Setting Up a Webhook

  1. Edit your form and go to the Actions tab.
  2. Select Trigger Webhook from the action type dropdown.
  3. Click Add Action.
  4. Configure the webhook settings.
  5. Save the form.

Configuration

Webhook URL (Required)

The URL that will receive the form data via POST request.

https://hooks.zapier.com/hooks/catch/123456/abcdef/

Content Type

Choose how the data is sent:

  • application/json – Sends the form data as a JSON object in the request body.
  • application/x-www-form-urlencoded – Sends the form data as URL-encoded form fields (default).

Authentication (Optional)

If the receiving endpoint requires authentication, you can set a custom header:

  • Header Name – The name of the authentication header (e.g., Authorization, X-API-Key, X-Auth-Token).
  • Header Value – The authentication value (e.g., Bearer your-api-token, sk_live_abc123).

Request Format

JSON Content Type

When using application/json, the request body contains the submission data as a JSON object:

{
    "name": "John Doe",
    "email": "john@example.com",
    "message": "Hello from Core Forms"
}

Form-Encoded Content Type

When using application/x-www-form-urlencoded, the data is sent as standard form fields:

name=John+Doe&email=john%40example.com&message=Hello+from+Core+Forms

Request Headers

Every webhook request includes:

  • Content-Type header matching the selected content type
  • Referer header set to the WordPress site URL
  • Custom authentication header (if configured)

Filtering the Request

Use the cf_webhook_request_args filter to modify the request before it is sent:

add_filter( 'cf_webhook_request_args', function( $args, $settings, $submission, $form ) {
    // Add a custom header
    $args['headers']['X-Form-ID'] = $form->ID;

    // Modify the body
    if ( $settings['content_type'] === 'json' ) {
        $data = json_decode( $args['body'], true );
        $data['source'] = 'website';
        $data['form_slug'] = $form->slug;
        $args['body'] = json_encode( $data );
    }

    return $args;
}, 10, 4 );

Handling the Response

The cf_webhook_response action fires after the request completes, giving you access to the response:

add_action( 'cf_webhook_response', function( $response, $settings, $submission, $form ) {
    if ( is_wp_error( $response ) ) {
        error_log( 'Webhook failed: ' . $response->get_error_message() );
        return;
    }

    $status_code = wp_remote_retrieve_response_code( $response );
    $body = wp_remote_retrieve_body( $response );

    if ( $status_code >= 400 ) {
        error_log( "Webhook returned $status_code: $body" );
    }
}, 10, 4 );

Multiple Webhooks

You can add multiple webhook actions to a single form. Each webhook runs independently with its own URL, content type, and authentication settings. All webhooks fire on every successful submission.

Error Handling

Webhook requests use WordPress’s wp_remote_post() function. If the request fails (network error, timeout, etc.), the function returns a WP_Error. The form submission still succeeds from the user’s perspective. Webhook failures do not prevent the success message from being shown.

If you need to track webhook failures, use the cf_webhook_response action to log errors.