HMAC SHA-256 · Retry · Idempotency · Sandbox

Signed webhooks for enterprise clients

How your system receives notifications from the workshop when something changes on an order, a delivery, an invoice, a quality alert or a catalogue item. Webhooks are signed, delivered with unique identifiers and retried with exponential backoff. Setup is from the customer portal against a valid HTTPS endpoint.

How a webhook is signed

Each webhook is signed with HMAC SHA-256. The signature is calculated over the raw request body — unprocessed — concatenated with the timestamp and a unique event identifier. The signature is delivered in the X-Corp-MX-Signature header in hex format. You recalculate the signature with the shared secret and compare with the received signature. If they do not match, the webhook is discarded.

Headers arriving with each webhook are X-Corp-MX-Signature with the HMAC signature, X-Corp-MX-Timestamp with the UNIX timestamp in seconds at send time, X-Corp-MX-Event-Id with the unique event identifier — useful for idempotency — and X-Corp-MX-Event-Type with the event type — order.created, order.approved, order.shipped, invoice.issued, among others.

Order events

Order events cover the full lifecycle. order.created when an order is registered after quote approval. order.in_production when production kicks off. order.stage_changed when a stage advances — cutting, sewing, decoration, packing. order.quality_check when the order passes quality inspection. order.shipped when the order leaves the workshop with the carrier tracking number. order.delivered when delivery is confirmed with receipt.

For customers with multiple plants, the order.stage_changed event includes the plant identifier. For runs with multiple lines, the order.line_completed event fires when each line finishes production, before the consolidated batch. This lets the customer know when a line is ready without waiting for the full order.

Shipment events

Shipment events cover the logistics lifecycle. shipment.created when the tracking number is generated with the carrier. shipment.in_transit when the shipment is en route with the carrier's first update. shipment.out_for_delivery when the shipment goes out for delivery. shipment.delivered when delivery is confirmed with the recipient name and, when applicable, the scanned signature.

For multi-stop deliveries — multi-site, multi-venue events — the shipment.stop_completed event fires when each stop is confirmed. The information includes the address, the receiving lead, the pieces delivered and the signature when applicable. Traceability is kept for the programme's warranty period.

Invoice and quality events

Invoice events cover the billing cycle. invoice.issued when the CFDI 4.0 invoice is stamped by SAT and available for download. invoice.paid when payment is confirmed per the agreed payment method and timeline. invoice.canceled when the invoice is cancelled for the stated reason and re-billing is issued where applicable.

Quality events cover non-conformities and corrective actions. quality.non_conformity_opened when an 8D is opened for a non-conformance detected in production or reported by the customer. quality.non_conformity_contained when immediate containment is executed. quality.non_conformity_closed when the 8D is closed with the corrective action verified. The customer can subscribe to all quality events or only to those affecting their orders.

Retries and failure handling

When a webhook fails — endpoint returns a status code outside the 2xx range — the system retries automatically. The retry policy is five attempts with exponential backoff: at sixty seconds, five minutes, thirty minutes, two hours and twelve hours. When the last attempt fails, the event sits in a manual review queue and both the workshop and the customer's technical leads are notified.

The system never delivers an event twice without you knowing. Each event carries a unique identifier in the X-Corp-MX-Event-Id header. You store the identifier and, on receiving an event, verify you have not processed it before. Idempotency is maintained by identifier — the second event with the same identifier is discarded.

Setup from the customer portal

Customers configure webhooks from the portal — available via SSO — with a valid HTTPS endpoint. For each event the customer selects whether to receive it. For runs with selective subscription — order events only, no quality — the customer ticks the events they require. Configuration is saved and applied instantly with no maintenance window.

For customers with separated environments — sandbox and production — two independent endpoints are managed. The sandbox delivers events with fictitious data for testing. Production delivers real events from customer orders. The customer can test integration in the sandbox before moving the endpoint to production with a single change in the portal.

Customer-side best practices

We recommend four practices. First, validate the HMAC SHA-256 signature before processing the body — if the signature does not match, discard. Second, validate the timestamp with five-minute tolerance — if the event is more than five minutes old, discard to prevent replay attacks. Third, maintain idempotency by event identifier — store the identifier in a table with twenty-four-hour TTL.

Fourth, respond fast — the endpoint must return a 2xx code within five seconds. If internal processing takes longer, the customer returns 2xx immediately and processes the webhook asynchronously with a background job. When the endpoint returns 5xx or times out, the system treats it as failure and triggers the retry.

Set up your webhooks with Corp-Merch.MX

If your technical team requires webhook integration with your operations stack, let's talk. We deliver the sandbox endpoint, the signing secret and full documentation in your format.



Webhooks are delivered to clients on an active programme with a signed usage agreement. Documentation may update without prior notice; major versions are communicated with thirty days' notice. Corp-Merch.MX is a Mexican workshop for corporate merch; we operate independently.