The Webhooks API enables Order Daemon to receive and process events from external services: payment gateways, automation platforms, and third-party integrations.
Base URL: /wp-json/odcm/v1/webhooks/
Authentication: Webhook endpoints use service-specific authentication (signatures, shared secrets) rather than WordPress authentication.
Gateway webhook endpoint
POST /webhooks/{gateway}
Receive webhook events from supported gateways and services.
Supported gateways:
stripe– Stripe payment events (comprehensive coverage)paypal– PayPal IPN and webhook events (full lifecycle)generic– Flexible adapter for any other service
Webhook URL format: https://yoursite.com/wp-json/odcm/v1/webhooks/{gateway}
Named connection variant: POST /webhooks/generic/{connection} – use this to distinguish multiple generic integrations by a stable connection name (e.g. zapier, make).
Note: All webhook POST endpoints always return HTTP 200, even on processing errors. This is intentional – returning non-200 would cause most gateways to retry delivery. Check the
successfield in the response body to determine outcome.
Response (success): {success: true, message: "Processed N event(s)", events_processed: N, process_id: "...", execution_time: "...ms"}
Response (error): {success: false, message: "...", process_id: "..."} – HTTP 200
Gateway discovery and management
GET /webhooks/gateways
Get comprehensive information about all available webhook gateways.
Authentication: Requires manage_woocommerce.
Response includes: gateway name and display info, available event types, webhook and test URLs, adapter status and capabilities.
GET /webhooks/test/{gateway}/events
Get available test event types for a specific gateway.
Authentication: Requires manage_woocommerce.
GET /webhooks/health
Public health check – no authentication required.
Response: {status: "healthy", timestamp, version, endpoints: {paypal, stripe, generic}, adapters: [...]}
POST /webhooks/test/{gateway}
Test a webhook endpoint with sample data.
Parameters:
gateway(string, required) – gateway identifierevent_type(string, optional) – specific event type (default:payment_completed)
Response includes: test success status, test ID for tracking, processing results, performance metrics, test recommendations.
Webhook security
Signature verification
- Stripe –
Stripe-Signatureheader with HMAC-SHA256 - PayPal – Certificate verification via
PayPal-Transmission-Sig,PayPal-Cert-Id, etc. - Generic – HMAC-SHA256 shared secrets via a configurable header (connection setting
hmac_header, defaulting tox-signature). If no connection is configured the endpoint operates in permissive mode – all requests pass.
Event processing flow
- Receive – verify signature, parse and validate payload, extract order reference.
- Map to universal event – convert gateway-specific data to standard format, enrich with WooCommerce order context.
- Trigger rule evaluation – find applicable rules, evaluate conditions, execute matching actions.
- Record audit trail – log webhook reception, rule evaluations, and outcomes.
Gateway-specific features
Stripe
The adapter normalizes raw Stripe webhook events to internal event type IDs. These IDs are what getSupportedEventTypes() returns and what the EventTypeCondition component matches against. The UniversalEvent.eventType property uses the hierarchical format payment.stripe.{original_event_type}.
52 event types are supported:
| Category | Event type IDs |
|---|---|
| Payment Intent | payment_intent_created, payment_intent_succeeded, payment_intent_payment_failed, payment_intent_canceled, payment_intent_requires_action, payment_intent_processing |
| Charge | charge_succeeded, charge_failed, charge_pending, charge_captured, charge_updated, charge_refunded |
| Dispute | charge_dispute_created, charge_dispute_updated, charge_dispute_closed, charge_dispute_funds_withdrawn, charge_dispute_funds_reinstated |
| Refund | refund_created, refund_updated, refund_failed |
| Subscription | customer_subscription_created, customer_subscription_updated, customer_subscription_deleted, customer_subscription_trial_will_end, customer_subscription_paused, customer_subscription_resumed |
| Invoice | invoice_created, invoice_finalized, invoice_payment_succeeded, invoice_payment_failed, invoice_payment_action_required, invoice_upcoming, invoice_voided |
| Customer | customer_created, customer_updated, customer_deleted, customer_source_created, customer_source_updated, customer_source_deleted |
| Payout | payout_created, payout_updated, payout_paid, payout_failed, payout_canceled |
| Setup Intent | setup_intent_created, setup_intent_succeeded, setup_intent_setup_failed, setup_intent_canceled |
| Price / Product | price_created, price_updated, product_created, product_updated |
Features: automatic order lookup by Stripe ID or metadata, subscription lifecycle management, dispute and refund handling.
Note: The
EventTypeConditionrule component Pro uses a separate generic vocabulary (payment_completed,subscription_cancelled, etc.) mapped from WooCommerce hooks – not the adapter-specific IDs listed above. The adapter event type IDs are used for adapter capability declaration (getSupportedEventTypes()) and appear in theUniversalEvent.eventTypefield aspayment.stripe.{original_event_type}.
PayPal
The adapter handles both IPN (form-encoded) and webhook (JSON) formats. Event type IDs follow the same normalized format. The UniversalEvent.eventType uses payment.paypal.{original_event_type}.
38 event types are supported:
| Category | Event type IDs |
|---|---|
| Payment | payment_created, payment_completed, payment_denied, payment_pending, payment_failed, payment_refunded, payment_reversed, payment_voided |
| Subscription | subscription_created, subscription_approved, subscription_cancelled, subscription_suspended, subscription_reactivated, subscription_completed, subscription_expired |
| Recurring | recurring_payment, recurring_payment_profile_created, recurring_payment_failed, recurring_payment_skipped, recurring_payment_suspended, recurring_payment_cancelled |
| Renewal | renewal_payment_processing, renewal_payment_completed, renewal_payment_failed, renewal_payment_pending |
| Trial | trial_started, trial_ended |
| Dispute | dispute_opened, dispute_resolved, dispute_won, dispute_lost |
| Express Checkout | express_checkout_created, express_checkout_completed |
| Mass Payment | mass_payment_completed, mass_payment_failed |
| Authorization | authorization_created, authorization_voided, authorization_expired |
Features: both IPN (form-encoded) and webhook (JSON) formats, automatic order lookup by transaction ID, PayPal certificate verification.
Generic adapter
The generic adapter accepts any JSON payload and normalizes it to a UniversalEvent. It is designed for services without a dedicated adapter (Zapier, Make, custom webhooks).
12 built-in event types are recognized:
| Category | Event type IDs |
|---|---|
| Payment | payment_completed, payment_failed, payment_pending, payment_refunded, payment_cancelled |
| Order | order_updated, order_completed, order_cancelled |
| Subscription | subscription_created, subscription_cancelled, subscription_renewed |
| Custom | custom_event – fallback for unrecognized types |
Any string not in this list is passed through as-is and stored in the audit log – you are not limited to these values.
Features: flexible field mapping, automatic extraction of order IDs and transaction IDs, configurable HMAC authentication, nested payload support.
Custom gateway integration
Extend AbstractGatewayAdapter and register via the odcm_register_gateway_adapters hook:
class CustomGatewayAdapter extends OrderDaemonCompletionManagerCoreEventsAdaptersAbstractGatewayAdapter {
public function __construct() {
parent::__construct('custom_gateway');
}
public function getSupportedEventTypes(): array {
return ['payment_completed', 'payment_failed'];
}
public function canHandle(array $input): bool {
return isset($input['payload']['custom_gateway_event']);
}
public function validateAuthenticity(array $input): bool {
$signature = $input['headers']['x-custom-signature'] ?? '';
$secret = get_option('custom_gateway_secret', '');
$expected = hash_hmac('sha256', json_encode($input['payload']), $secret);
return hash_equals($expected, $signature);
}
public function normalize(array $input): array {
$payload = $input['payload'] ?? [];
$event = new OrderDaemonCompletionManagerCoreEventsUniversalEvent([
'eventType' => $this->mapEventType($payload['event']),
'sourceGateway' => 'custom_gateway',
'primaryObjectType' => 'order',
'primaryObjectID' => $payload['order_id'] ?? null,
'transactionID' => $payload['transaction_id'] ?? null,
'amount' => $payload['amount'] ?? null,
'currency' => $payload['currency'] ?? 'USD',
'rawData' => $payload,
]);
return [$event];
}
public function computeIdempotencyKey(array $input): string {
$payload = $input['payload'] ?? [];
return 'custom_gateway_' . ($payload['transaction_id'] ?? md5(json_encode($payload)));
}
protected function extractTransactionId(array $payload): ?string {
return $payload['transaction_id'] ?? null;
}
protected function extractGatewaySpecificMetadata(array $input): array {
return ['event_type' => $input['payload']['event'] ?? null];
}
protected function mapEventType(string $event): string {
return [
'payment.success' => 'payment_completed',
'payment.failure' => 'payment_failed',
][$event] ?? 'custom_event';
}
}
add_action('odcm_register_gateway_adapters', function ($router) {
$router->registerAdapter(new CustomGatewayAdapter());
});See Creating custom rule components and Hooks and filters reference for full adapter documentation.