> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.oryxa.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive Webhook Events from Connected Integrations

> Synq receives inbound webhook events from your connected storefronts, verifies them with HMAC-SHA256, and automatically reconciles orders and catalog data.

When activity happens in your connected storefronts — a new order placed in Shopify, an order updated in WooCommerce, a product change on Amazon — those platforms send webhook events directly to Synq. Synq receives, authenticates, and processes each event, automatically reconciling the data into your orders and catalog without any manual action on your part.

This page explains how that inbound webhook pipeline works, how Synq verifies event authenticity, and what you need to configure to keep the flow running.

***

## How inbound webhooks work

When you connect a commerce platform via the [Integrations flow](/guides/integrations), Synq registers your workspace as a webhook destination with that platform. From that point on:

1. An event occurs on the connected platform (e.g. a customer places an order on your Shopify store).
2. The platform sends an HTTP `POST` to Synq's webhook endpoint.
3. Synq verifies the HMAC signature on the request to confirm it is authentic.
4. Synq looks up the connection and tenant that owns the event.
5. Synq enqueues a background workflow to map the event into your Synq orders and catalog.

You do not need to build or host your own webhook receiver — Synq handles the entire inbound pipeline.

***

## Webhook endpoint

Synq's inbound webhook endpoint is:

```
POST /unified/webhook
```

This endpoint is **public** — it does not require an `Authorization` header or tenant headers. Instead, every request is authenticated using HMAC-SHA256 signature verification.

***

## HMAC signature verification

Every inbound webhook carries an `X-Unified-Signature` header containing a hex-encoded HMAC-SHA256 digest of the raw request body, computed using your webhook secret.

Synq verifies this signature on every request. Requests with a missing, invalid, or mismatched signature are rejected with `401 Unauthorized`.

**How the signature is computed**

```
HMAC-SHA256(key=WEBHOOK_SECRET, message=RAW_REQUEST_BODY)
```

The resulting bytes are hex-encoded and placed in the `X-Unified-Signature` header.

<Note>
  Synq verifies incoming webhooks using HMAC-SHA256. Your webhook secret is available in your Synq dashboard under **Integrations**. Keep this secret safe — it is used to confirm that every inbound event genuinely originated from a platform connected to your account.
</Note>

**Example verification (Node.js)**

```js theme={null}
const crypto = require("crypto");

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  // Use a timing-safe comparison to prevent timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature, "utf8"),
    Buffer.from(expected, "utf8")
  );
}
```

**Example verification (Python)**

```python theme={null}
import hmac
import hashlib

def verify_webhook_signature(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        raw_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)
```

***

## Webhook payload structure

Every inbound webhook has a consistent JSON envelope regardless of the source platform. The payload is sent by the connected commerce platform and normalized by Synq before processing.

**Sample payload — order created event**

```json theme={null}
{
  "connection_id": "conn_shopify_8f3a2b",
  "event": "accounting.order.created",
  "data": {
    "id": "shopify_order_9988776655",
    "currency": "USD",
    "line_items": [
      {
        "item_id": "variant_abc001",
        "sku": "TSHIRT-BLK-M",
        "name": "Classic Black T-Shirt — Medium",
        "quantity": 2,
        "unit_amount": 29.99
      },
      {
        "item_id": "variant_def002",
        "sku": "HAT-BLU-OS",
        "name": "Blue Baseball Cap",
        "quantity": 1,
        "unit_amount": 19.99
      }
    ]
  }
}
```

<ResponseField name="connection_id" type="string">
  The connection ID that received the event. Synq uses this to look up your tenant and organization automatically.
</ResponseField>

<ResponseField name="event" type="string">
  The event type. For example, `"accounting.order.created"` or `"accounting.order.updated"`.
</ResponseField>

<ResponseField name="data" type="object">
  The raw event payload from the source platform, normalized into a consistent schema. The shape varies by event type.

  <ResponseField name="data.id" type="string">
    The external order or entity ID from the source platform.
  </ResponseField>

  <ResponseField name="data.currency" type="string">
    Three-letter ISO 4217 currency code for the order. Defaults to `USD` if not provided by the platform.
  </ResponseField>

  <ResponseField name="data.line_items" type="array">
    The line items in the order. Each item contains `item_id`, `sku`, `name`, `quantity`, and `unit_amount`.
  </ResponseField>
</ResponseField>

***

## What happens after Synq receives a webhook

Once Synq authenticates and parses an inbound webhook, it automatically:

1. **Resolves tenant context** — Synq maps the `connection_id` to the correct tenant and organization in your workspace. Events from unrecognized or inactive connections are rejected.
2. **Enqueues a background workflow** — For order events, Synq starts a durable workflow that maps the platform-native order into a Synq order. This workflow runs with automatic retries, so transient failures on your connected platform do not result in lost data.
3. **Reconciles into your catalog and orders** — Line items are matched to your Synq product variants by `item_id` or `sku`. A fully reconciled Synq order is created with the correct channel, currency, and fulfillment details, ready for your operations team.

<Note>
  Synq deduplicates inbound orders using an idempotency key derived from the `connection_id` and the external order ID. Re-delivering the same webhook event will not create duplicate orders.
</Note>

***

## Supported events

| Event                      | Description                                                 |
| -------------------------- | ----------------------------------------------------------- |
| `accounting.order.created` | A new order was placed on the connected platform.           |
| `accounting.order.updated` | An existing order was modified (status, fulfillment, etc.). |

<Tip>
  Additional event types for product changes, inventory updates, and customer records are on the roadmap.
</Tip>
