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

# Webhooks (Advanced)

Use the **Webhooks** page to subscribe to real-time events from fabric Dropship. Webhooks allow your external systems to receive automatic updates when key actions occur, such as inventory changes, order events, or shipment updates.

Once configured, fabric sends an HTTP request to your specified URL whenever a subscribed event occurs. You can view and manage all configured webhooks, including their delivery status, from this page.

## Supported Webhook Events

You can subscribe to the following event types. When an event occurs, fabric sends a real-time HTTP request to your configured webhook endpoint.

### Orders

| **Event**                         | **Description**                                                      |
| :-------------------------------- | :------------------------------------------------------------------- |
| **Order Created**                 | Triggered when a new order is placed.                                |
| **Order Canceled**                | Triggered when an order is canceled.                                 |
| **Order Returned**                | Triggered when a return is initiated for an order.                   |
| **Order Ship To Address Updated** | Triggered when a retailer updates the shipping address for an order. |

### Connections

| **Event**                  | **Description**                                                      |
| :------------------------- | :------------------------------------------------------------------- |
| **Connection Created**     | Triggered when a supplier-retailer connection is created.            |
| **Connection Established** | Triggered when a connection becomes active and ready for order flow. |

### Proposals

| **Event**                       | **Description**                                              |
| :------------------------------ | :----------------------------------------------------------- |
| **Proposal Approved**           | Triggered when a product proposal is approved by a merchant. |
| **Proposal Completed**          | Triggered when a proposal is marked as complete.             |
| **Proposal Declined**           | Triggered when a proposal is declined by a merchant.         |
| **Proposal Revised**            | Triggered when a proposal is updated by the supplier.        |
| **Proposal Collaborator Added** | Triggered when a collaborator is added to a proposal.        |
| **Proposal Owner Reassigned**   | Triggered when ownership of a proposal is reassigned.        |
| **Proposal Pricing Approved**   | Triggered when proposed pricing is approved.                 |
| **Proposal Product Approved**   | Triggered when a product within a proposal is approved.      |
| **Proposal Product Rejected**   | Triggered when a product within a proposal is rejected.      |
| **Proposal Variant Approved**   | Triggered when a product variant is approved.                |
| **Proposal Variant Rejected**   | Triggered when a product variant is rejected.                |
| **Proposal Variant Removed**    | Triggered when a product variant is removed from a proposal. |

### Returns (RMAs)

| **Event**               | **Description**                                                      |
| :---------------------- | :------------------------------------------------------------------- |
| **RMA Approved**        | Triggered when a return merchandise authorization (RMA) is approved. |
| **RMA Rejected**        | Triggered when an RMA request is rejected.                           |
| **RMA Completed**       | Triggered when an RMA is marked as completed.                        |
| **RMA Return Approved** | Triggered when the return items within an RMA are approved.          |
| **RMA Return Received** | Triggered when returned items are physically received.               |
| **RMA Return Rejected** | Triggered when returned items are rejected during processing.        |

## Adding a webhook

1. Click your business name in the menu at the top of the page in Dropship and click **Supplier Settings**.

   The **Supplier Settings** page is displayed.

2. Click **Webhooks (Advanced)**.

   The **Webhooks** page is displayed.

3. On the **Webhooks** page, click **Add Webhook**.

   The **Add Webhook** window is displayed.

4. In the **Topic** field, select the event you want to subscribe to.

5. In the **Method** field, select the HTTP method to use, whether **POST**, **PUT**, or **PATCH**.

   This determines how the event payload is sent to your server.

6. In the **URL** field, enter the publicly accessible endpoint where you want to receive the webhook.

7. In the **Status** field, select whether the webhook should be **Enabled** or **Disabled**.

8. Click **Add Webhook** to save the configuration.

The webhook is created.

<Note> Your endpoint must respond with a 2xx HTTP status code to confirm successful delivery. If a webhook fails, fabric may attempt retries based on a backoff strategy. </Note>

## Viewing webhook history

After configuration, you can monitor recent deliveries and failures on the **Webhooks** page in the **Webhook History** section. This helps confirm that events are triggering correctly and that your system is responding as expected.

### Webhook automatic retry timing

Retries do not occur at fixed intervals. Instead, fabric uses an exponential backoff strategy combined with a small random jitter to help prevent the “thundering herd” problem—where many clients retry at the same time.

A typical retry schedule looks like this:

* 30 seconds after the first failure
* 1 minute later
* 2 minutes later
* 4 minutes later
* 8 minutes later
* 16 minutes later
* 32 minutes later
* 64 minutes later
* 2 hours later
* 2 hours later (maximum delay)

The maximum delay between retries is 2 hours. Each retry also includes a small random delay (up to 30 seconds) to spread out retry traffic and reduce server load.

If a webhook continues to fail after reaching 10 retries without receiving a successful response, it will be automatically disabled.

Disabling a webhook after repeated failures is a deliberate safeguard to protect system reliability, security, and user experience.

fabric recognizes that this approach has tradeoffs. Disabling a webhook can result in missed events if the endpoint is down temporarily, and not all failures indicate the same level of severity (for example, a temporary 500 error versus a permanent 404). However, allowing a webhook to fail indefinitely introduces larger risks.

The 10-failure threshold helps fabric:

* Prevent notification overload by stopping repeated delivery attempts to an endpoint that is consistently unavailable, which could otherwise strain internal queues and downstream systems.
* Maintain system stability by avoiding endless retry loops to non-functional endpoints.
* Address potential security concerns, as persistent failures may indicate misconfiguration or malicious behavior.
* Improve visibility and user experience by clearly signaling that action is required, rather than allowing silent, ongoing failures.

This behavior aligns with industry standards and balances reliability, security, and transparency. Once the underlying issue is resolved, the webhook can be re-enabled to resume event delivery.

## Webhook Verification Process

fabric Dropship signs all webhook requests using an **HMAC-SHA256** signature to verify authenticity and protect against tampering.

<Note> Treat your webhook secret as confidential information and store it securely. Unauthorized access to the secret would allow malicious actors to forge webhooks that appear authentic to your application. </Note>

### Generating a webhook secret

You must generate a webhook secret before verifying signatures.

1. Go to **Supplier Settings** > **Webhooks**.

2. Click **Generate Secret**.

3. Reveal the secret and copy it for use in your integration.

<Note> If the secret is ever compromised, click **Generate New Secret** and confirm to replace it. </Note>

### Using the API

1. To generate a new secret, send a POST request to:

```bash theme={null}
/v1/brands/{id}/webhooks/webhook-secret/
```

2. (Optional) to replace an existing secret, include the following payload in your request:

```json theme={null}
{ "replace": true }
```

3. A new webhook secret will be generated and returned in the response:

```json theme={null}
{
    "webhook_secret": "lpXQv26yusotoO3oVr1uHiE1hEhco8vx"
}
```

### Verifying a webhook

After you generate a webhook secret, fabric Dropship signs every webhook request using that secret. The signature is included in the fabric-dropship-signature header. To verify that a webhook is authentic, follow these steps:

1. Retrieve the raw webhook body.

   Use the exact body received from the request, without modifying whitespace, formatting, or character encoding.

2. Generate the HMAC. Create an HMAC-SHA256 hash using:

   Create an HMAC-SHA256 hash using your webhook secret and the raw request body.

3. Compare the signatures.

   Compare your computed hash to the value in the fabric-dropship-signature header. If the values match, the webhook is authentic. If they do not match, the webhook may be unverified and should be rejected.

**Webhook Secret:**

```
lpXQv26yusotAO3oVr1yHiE1hEhco8vx
```

**Raw Body:**

```json theme={null}
{"id": 1234, "purchase_order_number": "ABC-001", "status": "closed"}
```

**Expected Signature:**

```
fabric-dropship-signature: 5d1cae4e1081325679f6e50a52ea28193e3d6871536981f0de2ed34bfc788c2d
```

By performing these checks, you can ensure that incoming webhook events are authentic and safe to process.

<Accordion title="Example Python Implementation">
  ```Python theme={null}
  import hashlib
  import hmac
  import os

  def hmac_is_valid(body, secret, signature):
      _hash = hmac.new(secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256)
      hmac_calculated = _hash.hexdigest()
      return hmac.compare_digest(hmac_calculated.encode('utf-8'), signature.encode('utf-8'))

  signature = '5d1cae4e1081325679f6e50a52ea28193e3d68715b36981f0de2ed34fc788c2d'
  raw_body = '{"id": 1234, "purchase_order_number": "ABC-001", "status": "closed"}'
  webhook_secret = os.environ.get('DROPSHIP_WEBHOOK_SECRET') # read secret from env vars
  is_authentic = hmac_is_valid(raw_body, webhook_secret, signature)
  print(f'Webhook is authentic? {is_authentic}') # True
  ```
</Accordion>

### Notifications for disabled webhooks

When a webhook fails, it is retried 10 times. After a webhook fails 10 times, it is automatically disabled.

You can subscribe to notifications that alert you when a webhook has been disabled.

There are two types of disabled webhook notifications:

* Webhook failed to deliver
* Webhook disabled after failed attempts

You can opt into one or both of these notifications by taking the following steps:

1. Click your business name in the menu at the top of the page in Dropship and click **Supplier Settings**.

   The **Supplier Settings** page is displayed.

2. Click **Notifications**.

   The **Notifications** page is displayed.

3. In the **Webhook Notifications** section, enter an email address or distribution list in one or both of the **Webhook Failed to Deliver** or **Webhook Disabled After Failed Attempts** fields.

   To enter multiple addresses, separate them by commas.

4. Click the toggle button next to the notifications you want to enable.

Dropship will send email alerts to the recipients you specified when the selected events occur.
