Webhook Module Architecture & Requirements
1. Architectural Space (Folder Structure)
The Webhook module will be fully integrated into the sp-laravel-api core engine, following the same pattern as the Attachments module.
- Configuration:
config/webhooks.php(Defines tables usingRecordTableTypefor instant CRUD APIs). - Migrations:
database/migrations/xxxx_create_sp_webhooks_tables.php - Service:
src/Services/WebhookService.php(Handles payload formatting, HMAC signature generation, and dispatching). - Jobs:
src/Jobs/DispatchWebhookJob.php(Asynchronous queue processing to prevent API blocking). - Triggers:
src/Triggers/WebhookTrigger.php(Global listener using#[RecordTrigger]forafterCreate,afterUpdate, andafterDelete).
2. Database Schema Requirements
The module requires 3 tables to ensure robust, enterprise-ready webhook management and auditing.
A. sp_webhook_endpoints (The Destination)
Stores the external URLs that will receive the webhook payloads.
id(uuid, primary key)tenant_id(string, nullable, indexed)name(string) - e.g., "Zapier Integration", "Slack Notifier"url(string) - The destination HTTP/HTTPS URLsecret(string) - Used to sign the payload (HMAC SHA256) for receiver verificationis_active(boolean, default: true) - Toggle to pause/resume webhookstimestamps
B. sp_webhook_subscriptions (The Listeners)
Defines which events an endpoint is interested in.
id(uuid, primary key)tenant_id(string, nullable, indexed)endpoint_id(uuid, foreign key tosp_webhook_endpoints)table_name(string) - e.g.,users,invoices, or*for all tablesevent(string) - e.g.,created,updated,deleted, or*for all eventstimestamps
C. sp_webhook_deliveries (The Audit Log)
Crucial for debugging, this logs every attempt to send a webhook.
id(uuid, primary key)tenant_id(string, nullable, indexed)endpoint_id(uuid, foreign key tosp_webhook_endpoints)event(string) - e.g.,invoices.createdpayload(json) - The exact data payload sentresponse_status(integer, nullable) - HTTP status code (e.g., 200, 404, 500)response_body(text, nullable) - The response received from the endpointstatus(enum:pending,success,failed)timestamps
3. Core Logic & Integration Flow
- The Trigger: The
WebhookTriggerclass uses#[RecordTrigger]attributes to hook into the globalafterCreate,afterUpdate, andafterDeletelifecycle events of theRecordService. - The Matcher: When a record is modified (e.g., an invoice is created), the trigger queries
sp_webhook_subscriptionsto find active endpoints listening toinvoices.createdfor the currenttenant_id. - The Dispatch: For every matching subscription, a
DispatchWebhookJobis dispatched to Laravel's queue system. - The Execution: The Job processes asynchronously:
- Generates an HMAC SHA256 signature using the endpoint's
secret. - Sends the HTTP POST request using Laravel's
Httpfacade. - Records the outcome (success/failure, status code, response body) in the
sp_webhook_deliveriestable.
- Generates an HMAC SHA256 signature using the endpoint's
4. Configuration (config/webhooks.php)
The tables will be exposed via the dynamic API engine, allowing frontend applications to build webhook management UIs instantly.
php
<?php
use Sopheak\Core\Types\RecordTableType;
return [
'enabled' => env('SP_LARAVEL_API_WEBHOOKS_ENABLED', true),
'tables' => [
'sp_webhook_endpoints' => new RecordTableType(
table: 'sp_webhook_endpoints',
pmsName: 'webhook',
hasTenantId: true,
isAuthRead: true,
isAuthWrite: true,
// ... columns definition
),
'sp_webhook_subscriptions' => new RecordTableType(
table: 'sp_webhook_subscriptions',
pmsName: 'webhook',
hasTenantId: true,
isAuthRead: true,
isAuthWrite: true,
// ... columns definition
),
'sp_webhook_deliveries' => new RecordTableType(
table: 'sp_webhook_deliveries',
pmsName: 'webhook',
hasTenantId: true,
isAuthRead: true,
isAuthWrite: false, // Deliveries should be read-only via API
// ... columns definition
),
],
];