Webhooks

How stores send orders to Preset Bridge and how Preset Bridge sends delivery results back.

Webhook endpoint

All store webhooks are sent to a single endpoint pattern:

Webhook URL
POST /api/webhooks/<provider>/<integrationId>

Where:

  • <provider> is one of: shopify, woocommerce, or generic
  • <integrationId> is the unique ID of your store integration

Signature verification

Preset Bridge verifies the authenticity of incoming webhooks using HMAC signatures. The signature header differs by provider:

Provider Signature header Algorithm
Shopify X-Shopify-Hmac-Sha256 HMAC-SHA256 (Base64)
WooCommerce X-WC-Webhook-Signature HMAC-SHA256 (Base64)
Generic X-Webhook-Signature or X-NDSP-Signature HMAC-SHA256 (Hex, prefixed with sha256=)
Invalid signatures are rejected. Shopify integrations use the signing key copied from that Shopify store. WooCommerce and generic integrations use the secret generated by Preset Bridge when the integration is created.

Shopify payload

Shopify sends the full order object. Preset Bridge extracts line items and the customer's NDSP username from the order note or note attributes.

Shopify order webhook (relevant fields)
{
  "id": 5678901234,
  "order_number": 1042,
  "email": "customer@example.com",
  "note": "NDSP username: cortex_user_42",
  "note_attributes": [
    { "name": "ndsp_username", "value": "cortex_user_42" }
  ],
  "line_items": [
    {
      "sku": "STORM-LEAD-V2",
      "product_id": 7891234567890,
      "variant_id": 43210987654321,
      "title": "Storm Drive Lead Preset",
      "quantity": 1
    }
  ]
}
Username extraction: Preset Bridge checks note_attributes for a field named ndsp_username, cortex_username, or neural_dsp_username. If not found, it falls back to parsing the note field.

WooCommerce payload

WooCommerce sends the full order object. Preset Bridge extracts line items and looks for the NDSP username in order meta fields.

WooCommerce order webhook (relevant fields)
{
  "id": 1234,
  "order_key": "wc_order_abc123",
  "billing": {
    "email": "customer@example.com"
  },
  "meta_data": [
    { "key": "ndsp_username", "value": "cortex_user_42" }
  ],
  "line_items": [
    {
      "sku": "STORM-LEAD-V2",
      "product_id": 567,
      "variation_id": 890,
      "name": "Storm Drive Lead Preset",
      "quantity": 1
    }
  ]
}

Generic payload

The generic provider accepts a simplified JSON structure. Use this when integrating a custom store or platform.

Generic webhook payload
{
  "orderId": "order-1234",
  "customerEmail": "fan@music.com",
  "targetUsername": "cortex_user_42",
  "items": [
    {
      "sku": "STORM-LEAD-V2",
      "productId": "prod_123",
      "title": "Storm Drive Lead Preset",
      "quantity": 1
    }
  ]
}
Field Type Required Description
orderId string Yes Unique order identifier (used for deduplication)
customerEmail string No Customer's email for reference
targetUsername string Yes Customer's Cortex Cloud username
items array Yes List of purchased items to match against item mappings
items[].sku string No* Product SKU
items[].productId string No* Product ID
items[].title string No* Product title
items[].quantity number No Quantity purchased (default: 1)

* At least one identifier (sku, productId, or title) must be present to match an item mapping.

Webhook responses

Preset Bridge responds to webhooks synchronously:

Status Meaning
202 Webhook accepted and delivery queued
400 Invalid payload or missing required fields
401 Invalid or missing webhook signature
404 Integration not found
500 Internal processing error

Delivery result webhooks

Outbound webhook subscriptions send delivery state changes from Preset Bridge to your store or another HTTPS endpoint. Create them under Integrations → Outbound webhooks.

Each request includes these headers:

Header Value
Content-Type application/json
X-NDSP-Event The delivery event name, such as delivery.completed
X-NDSP-Signature sha256=<hmac-hex>, calculated over the exact request body
Delivery result payload
{
  "id": "f5ee5dc4-76fd-4d41-8ad7-19e132e9f5aa",
  "type": "delivery.completed",
  "createdAt": "2026-08-11T02:20:00.000Z",
  "integrationId": "store-integration-id",
  "deliveryId": "delivery-record-id",
  "delivery": {
    "orderId": "511",
    "eventId": "wc-511-stable-event-id",
    "status": "completed",
    "message": "Preset shared successfully"
  }
}

Subscriptions can be limited to one or more integration IDs. Use that restriction when one account operates several stores.

delivery.invalidated stops store-side completion and includes the merchant’s reason. delivery.reopened returns the order to review without starting another attempt.

WooCommerce: use the Resolution webhook URL shown in the plugin settings as the target. The WooCommerce setup guide lists the required events and the full test procedure.
Shopify and other platforms: Preset Bridge sends the result, but a platform app or callback receiver must apply it to the original order. Follow the Shopify guide or custom platform guide for that boundary.

Delivery result retries

Preset Bridge retries connection failures, timeouts, HTTP 408, HTTP 429 and HTTP 5xx responses after 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours and 24 hours. Other HTTP 4xx responses are permanent because they normally require a URL, secret or receiver change.

Open the subscription under Outbound webhooks to see its recent response codes and attempt status.

Retry behaviour

Deliveries that fail due to transient errors or wait for Cortex Cloud friendship are automatically retried. The delivery queue processes up to 5 jobs per minute.

You can also manually retry a failed delivery from the Integrations page in your dashboard. For deliveries that failed due to a missing or incorrect username, update the customer's NDSP username before retrying.