Official PHP SDK for Webhook Platform

Maintainers

Package info

github.com/vadymkykalo/webhook-platform-php

pkg:composer/webhook-platform/php

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.2.1 2026-03-01 17:59 UTC

This package is auto-updated.

Last update: 2026-03-18 09:32:33 UTC


README

Official PHP SDK for Hookflow.

Requirements

  • PHP 8.1+
  • ext-json
  • ext-curl

Installation

composer require webhook-platform/php

Quick Start

<?php

use Hookflow\Hookflow;

$client = new Hookflow(
    apiKey: 'wh_live_your_api_key',
    baseUrl: 'http://localhost:8080' // optional
);

// Send an event
$event = $client->events->send(
    type: 'order.completed',
    data: [
        'orderId' => 'ord_12345',
        'amount' => 99.99,
        'currency' => 'USD',
    ]
);

echo "Event created: {$event['eventId']}\n";
echo "Deliveries created: {$event['deliveriesCreated']}\n";

API Reference

Events

// Send event with idempotency key
$event = $client->events->send(
    type: 'order.completed',
    data: ['orderId' => '123'],
    idempotencyKey: 'unique-key'
);

Endpoints

// Create endpoint
$endpoint = $client->endpoints->create($projectId, [
    'url' => 'https://api.example.com/webhooks',
    'description' => 'Production webhooks',
    'enabled' => true,
]);

// List endpoints
$endpoints = $client->endpoints->list($projectId);

// Update endpoint
$client->endpoints->update($projectId, $endpointId, [
    'enabled' => false,
]);

// Delete endpoint
$client->endpoints->delete($projectId, $endpointId);

// Rotate secret
$updated = $client->endpoints->rotateSecret($projectId, $endpointId);
echo "New secret: {$updated['secret']}\n";

// Test endpoint connectivity
$result = $client->endpoints->test($projectId, $endpointId);
$status = $result['success'] ? 'passed' : 'failed';
echo "Test {$status}: {$result['latencyMs']}ms\n";

Subscriptions

// Subscribe endpoint to an event type
$subscription = $client->subscriptions->create($projectId, [
    'endpointId' => $endpoint['id'],
    'eventType' => 'order.completed',
    'enabled' => true,
]);

// List subscriptions
$subscriptions = $client->subscriptions->list($projectId);

// Update subscription
$client->subscriptions->update($projectId, $subscriptionId, [
    'eventType' => 'order.shipped',
    'enabled' => true,
]);

// Delete subscription
$client->subscriptions->delete($projectId, $subscriptionId);

Deliveries

// List deliveries with filters
$deliveries = $client->deliveries->list($projectId, [
    'status' => 'FAILED',
    'page' => 0,
    'size' => 20,
]);

echo "Total failed: {$deliveries['totalElements']}\n";

// Get delivery attempts
$attempts = $client->deliveries->getAttempts($deliveryId);
foreach ($attempts as $attempt) {
    echo "Attempt {$attempt['attemptNumber']}: {$attempt['httpStatus']} ({$attempt['latencyMs']}ms)\n";
}

// Replay failed delivery
$client->deliveries->replay($deliveryId);

Incoming Webhooks

Receive, validate, and forward webhooks from third-party providers (Stripe, GitHub, Twilio, etc.).

Incoming Sources

// Create an incoming source with HMAC verification
$source = $client->incomingSources->create($projectId, [
    'name' => 'Stripe Webhooks',
    'slug' => 'stripe',
    'providerType' => 'STRIPE',
    'verificationMode' => 'HMAC_GENERIC',
    'hmacSecret' => 'whsec_...',
    'hmacHeaderName' => 'Stripe-Signature',
]);

echo "Ingress URL: {$source['ingressUrl']}\n";

// List sources
$sources = $client->incomingSources->list($projectId);

// Update source
$client->incomingSources->update($projectId, $sourceId, [
    'name' => 'Stripe Production',
    'rateLimitPerSecond' => 100,
]);

// Delete source
$client->incomingSources->delete($projectId, $sourceId);

Incoming Destinations

// Add a forwarding destination
$dest = $client->incomingSources->createDestination($projectId, $sourceId, [
    'url' => 'https://your-api.com/webhooks/stripe',
    'enabled' => true,
    'maxAttempts' => 5,
    'timeoutSeconds' => 30,
]);

// List destinations
$dests = $client->incomingSources->listDestinations($projectId, $sourceId);

// Update destination
$client->incomingSources->updateDestination($projectId, $sourceId, $destId, [
    'enabled' => false,
]);

// Delete destination
$client->incomingSources->deleteDestination($projectId, $sourceId, $destId);

Incoming Events

// List incoming events (with optional source filter)
$events = $client->incomingEvents->list($projectId, [
    'sourceId' => $sourceId,
    'page' => 0,
    'size' => 20,
]);

// Get event details
$event = $client->incomingEvents->get($projectId, $eventId);

// Get forward attempts
$attempts = $client->incomingEvents->getAttempts($projectId, $eventId);

// Replay event to all destinations
$result = $client->incomingEvents->replay($projectId, $eventId);
echo "Replayed to {$result['destinationsCount']} destinations\n";

Webhook Signature Verification

Verify incoming webhooks in your endpoint:

<?php

use Hookflow\Webhook;
use Hookflow\Exception\HookflowException;

// Get raw request body
$payload = file_get_contents('php://input');
$headers = getallheaders();
$secret = getenv('WEBHOOK_SECRET');

try {
    // Option 1: Just verify
    Webhook::verifySignature($payload, $headers['X-Signature'] ?? '', $secret);

    // Option 2: Verify and parse
    $event = Webhook::constructEvent($payload, $headers, $secret);

    echo "Received {$event['type']}: " . json_encode($event['data']) . "\n";

    // Handle the event
    switch ($event['type']) {
        case 'order.completed':
            handleOrderCompleted($event['data']);
            break;
    }

    http_response_code(200);
    echo 'OK';

} catch (HookflowException $e) {
    error_log("Webhook verification failed: {$e->getMessage()}");
    http_response_code(400);
    echo 'Invalid signature';
}

Laravel Example

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Hookflow\Webhook;
use Hookflow\Exception\HookflowException;

class WebhookController extends Controller
{
    public function handle(Request $request)
    {
        $payload = $request->getContent();
        $headers = $request->headers->all();
        
        try {
            $event = Webhook::constructEvent(
                $payload,
                $headers,
                config('services.webhook.secret')
            );

            // Process event...
            
            return response('OK', 200);

        } catch (HookflowException $e) {
            return response('Invalid signature', 400);
        }
    }
}

Symfony Example

<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Hookflow\Webhook;
use Hookflow\Exception\HookflowException;

class WebhookController
{
    public function handle(Request $request): Response
    {
        $payload = $request->getContent();
        $headers = $request->headers->all();

        try {
            $event = Webhook::constructEvent(
                $payload,
                $headers,
                $_ENV['WEBHOOK_SECRET']
            );

            // Process event...

            return new Response('OK', 200);

        } catch (HookflowException $e) {
            return new Response('Invalid signature', 400);
        }
    }
}

Error Handling

<?php

use Hookflow\Exception\HookflowException;
use Hookflow\Exception\RateLimitException;
use Hookflow\Exception\AuthenticationException;
use Hookflow\Exception\ValidationException;

try {
    $client->events->send('test', []);
} catch (RateLimitException $e) {
    // Wait and retry
    $retryAfterMs = $e->getRetryAfterMs();
    echo "Rate limited. Retry after {$retryAfterMs}ms\n";
    usleep($retryAfterMs * 1000);
} catch (AuthenticationException $e) {
    echo "Invalid API key\n";
} catch (ValidationException $e) {
    echo "Validation failed: " . json_encode($e->getFieldErrors()) . "\n";
} catch (HookflowException $e) {
    echo "Error {$e->getStatusCode()}: {$e->getMessage()}\n";
}

Configuration

$client = new Hookflow(
    apiKey: 'wh_live_xxx',           // Required: Your API key
    baseUrl: 'https://api.example.com', // Optional: API base URL
    timeout: 30                      // Optional: Request timeout in seconds (default: 30)
);

Development

Running Tests

Local (requires PHP 8.1+):

composer install
composer test

Docker:

docker run --rm -v $(pwd):/app -w /app composer:2 sh -c "composer install && composer test"

License

MIT