Built for reliable sync. Not fragile one-shot delivery.

NovexERP exposes inbound webhook endpoints for connected providers. Events are signature-verified, stored idempotently, and processed through a retry-aware queue.

EVENTS

Webhook Ingestion

Receive provider events from Shopify and EasyPost with secure ingestion and resilient processing. Built for reliable synchronization, not fragile one-shot delivery.

Shopify webhooks arrive at /api/webhooks/shopify/* endpoints, with each topic routed to the appropriate handler. Every incoming payload is verified using the X-Shopify-Hmac-Sha256 header — NovexERP computes a SHA256 HMAC from the raw request body using the configured webhook secret and compares it against the header value. Only payloads with valid signatures are accepted, ensuring that events genuinely originated from Shopify and were not tampered with in transit.

EasyPost webhooks arrive at the POST /api/webhooks/easypost endpoint. These payloads carry tracking status updates for shipments created through the EasyPost integration. Signature verification uses the X-Hmac-Signature header with the same constant-time comparison approach. Keycloak identity events arrive at /api/keycloak/events with a bearer secret verified through constant-time comparison, logging LOGIN, LOGIN_ERROR, LOGOUT, and admin operations to the system_log table for security auditing.

All webhook endpoints follow the same architectural principle: return 200 immediately without waiting for processing. The endpoint reads the raw body, verifies the signature, stores the event, and responds — all within milliseconds. Heavy processing happens asynchronously in the background, which means provider retry logic never triggers due to slow responses. This fast-acknowledge pattern is critical for maintaining reliable webhook delivery from providers that enforce timeout limits.

Idempotent storage uses unique constraints on the webhook_id field to prevent duplicate events. When Shopify or EasyPost retries a delivery (which happens when they detect network issues or slow responses), the duplicate payload is safely rejected at the database level. For Shopify events, the unique constraint is on the combination of shop_domain and webhook_id, ensuring events from different shops never collide. This means you never process the same order twice, even if Shopify sends the same webhook multiple times.

Background event processing uses a claim-lock worker pattern designed to prevent concurrent processing of the same event. A cron job queries for pending events, then claims them by writing its hostname and PID to the event record in a single atomic update. Only the process that successfully claims an event processes it, eliminating race conditions when multiple workers run simultaneously. If processing fails, the event's attempt counter is incremented and it becomes eligible for retry. The default retry limit is 8 attempts with exponential backoff, giving temporary upstream issues time to resolve before marking an event as permanently failed.

Delivery status tracking follows a clear progression: events move from received to processing to either completed or failed. This status trail is visible in the webhook processing logs for debugging. SPS Commerce EDI polling at POST /api/sps/poll uses the same claim-lock pattern to download purchase order files from SPS directories, providing a consistent processing model across both push (webhook) and pull (polling) integration patterns. For integration-specific webhook details, see Shopify and EasyPost.

  • Shopify webhook endpoints with HMAC-SHA256
  • EasyPost webhook endpoint with signature verification
  • Fast 200 response (async processing)
  • Idempotent event storage
  • Claim-lock worker pattern
  • Configurable retry with exponential backoff
  • Delivery status tracking (received → completed/failed)
  • SPS Commerce EDI polling

How It Works

A provider such as Shopify or EasyPost sends an event to the corresponding webhook endpoint. The payload arrives as a POST request with a signature header that authenticates its origin.

NovexERP verifies the HMAC signature against the configured secret using constant-time comparison. Invalid signatures are rejected immediately with an appropriate error response, preventing unauthorized payloads from entering the system.

The event is stored idempotently in the database. If the same webhook has already been received (matched by webhook_id), the duplicate is safely ignored at the database constraint level. The endpoint returns 200 immediately, acknowledging receipt to the provider.

A background cron job claims pending events using a lock mechanism that writes the worker's hostname and PID to the event record. Only one worker can claim a given event, preventing duplicate processing even when multiple cron instances run concurrently.

If processing fails, the event is retried up to 8 times with exponential backoff. Event status is tracked from received through processing to completed or failed, providing full visibility into the webhook delivery pipeline for monitoring and debugging.

Modules Used

This feature is powered by these NovexERP modules.

Ready to see NovexERP in action?

Get a personalized demo tailored to your food manufacturing operation.

Request a Demo