Skip to content

Webhooks ​

Webhook triggering is the core feature of php-n8n/client.

php
$response = $client->webhooks()->trigger($webhook, $request);

Webhook URLs ​

Create a webhook from a PSR-7 URI:

php
use PhpN8n\Client\Webhooks\Webhook;

$webhook = Webhook::fromUri(
    $psr17->createUri('https://n8n.example.com/webhook/order-created')
);

The URL must be:

  • Non-empty.
  • Absolute.
  • http or https.
  • Valid according to PHP URL validation.
  • Built with a host.

Invalid webhook URLs throw InvalidArgumentException.

HTTP Methods ​

Webhooks use POST by default.

php
use PhpN8n\Client\Webhooks\WebhookMethod;

$webhook = $webhook->withMethod(WebhookMethod::Post);
$webhook = $webhook->withMethod('POST');

Supported methods:

Enum caseHTTP method
WebhookMethod::DeleteDELETE
WebhookMethod::GetGET
WebhookMethod::HeadHEAD
WebhookMethod::OptionsOPTIONS
WebhookMethod::PatchPATCH
WebhookMethod::PostPOST
WebhookMethod::PutPUT

Unsupported string methods throw InvalidArgumentException.

Headers And Query Parameters ​

Headers and query parameters can be placed on the webhook or on the request.

php
$webhook = Webhook::fromUri($uri)
    ->withHeader('X-Workflow-Source', 'checkout')
    ->withQueryParameter('environment', 'production');

$request = WebhookRequest::json(['orderId' => 'ORD-1001'])
    ->withHeader('X-Request-ID', 'req_123')
    ->withQueryParameter('trace', '1');

When the same header or query key exists in both places, request-level values replace webhook-level values.

Empty Requests ​

php
use PhpN8n\Client\Webhooks\WebhookRequest;

$response = $client->webhooks()->trigger(
    $webhook,
    WebhookRequest::empty(),
);

If no request is passed, the client sends an empty request.

JSON Requests ​

php
$response = $client->webhooks()->trigger(
    $webhook,
    WebhookRequest::json([
        'orderId' => 'ORD-1001',
        'total' => 129.50,
    ]),
);

JSON bodies are encoded with JSON_THROW_ON_ERROR. If no Content-Type header is already set, the client adds Content-Type: application/json.

Text Requests ​

php
$response = $client->webhooks()->trigger(
    $webhook,
    WebhookRequest::text('plain text payload'),
);

If no Content-Type header is already set, the client adds Content-Type: text/plain.

Stream Requests ​

php
$stream = $psr17->createStreamFromFile('/path/to/export.json');

$response = $client->webhooks()->trigger(
    $webhook,
    WebhookRequest::stream($stream)
        ->withHeader('Content-Type', 'application/json'),
);

Stream requests use the PSR-7 stream you provide. Set the content type yourself when n8n needs one.

Immutable Requests ​

Webhook and WebhookRequest are immutable. Methods such as withHeader(), withQuery(), and withJsonBody() return new instances.

php
$baseRequest = WebhookRequest::json(['type' => 'order']);

$productionRequest = $baseRequest
    ->withQueryParameter('environment', 'production');

$baseRequest remains unchanged.

Webhook Responses ​

trigger() returns WebhookResponse.

php
$statusCode = $response->statusCode();
$type = $response->type();
$body = $response->body();
$httpResponse = $response->httpResponse();
$reference = $response->executionReference();
$status = $response->status();

Response body handling:

ResponseResult
Empty bodyWebhookResponseType::None, body null.
JSON content typeJSON-decoded body, WebhookResponseType::Json.
Other content typeRaw string body, WebhookResponseType::Text.

If the response is marked as JSON but contains invalid JSON, the client throws InvalidWebhookResponseException.

Execution References From Webhook Responses ​

The resolver extracts an execution reference when the JSON response contains one of these shapes:

json
{ "executionId": "123" }
json
{ "execution_id": "123" }
json
{ "executionReference": { "id": "123" } }
json
{ "execution": { "id": "123" } }

Then you can track it:

php
$reference = $response->executionReference();

if ($reference !== null) {
    $result = $client->execution($reference)->wait();
}

The client also extracts execution status from status or execution.status when present.

Released under the MIT License.