> For the complete documentation index, see [llms.txt](https://fincart.gitbook.io/fincart-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://fincart.gitbook.io/fincart-api/webhooks/setup-your-webhooks.md).

# Setup your Webhooks

**Overview**

Fincart supports **Webhook Notifications** to **automatically update merchants' systems** whenever an order status changes. This allows merchants to receive **real-time order status updates**, eliminating the need for polling APIs and ensuring their system is always in sync.

You can configure a **primary webhook** and an optional **secondary webhook**. When both are set, Fincart sends the same payload to each destination independently — useful as a backup endpoint or a second system that also needs order updates.

**Webhook Setup Available from the Dashboard**

You can configure your webhook settings directly from the dashboard.

{% stepper %}
{% step %}

### Open the profile menu

Go to the **top-right corner** of the page and click the **profile dropdown menu**.

<figure><img src="https://1434135307-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fen1Z8JQlz13ZnLrnbUUt%2Fuploads%2FqXCPcBUbriQW99zGwCE3%2FScreenshot%202025-07-16%20at%207.12.28%E2%80%AFPM.png?alt=media&#x26;token=46ff13f5-1198-4159-9d46-d7f0c56ef809" alt="Profile dropdown menu"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Open Webhook Details

Select **Webhook Details** from the menu.

<figure><img src="https://1434135307-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fen1Z8JQlz13ZnLrnbUUt%2Fuploads%2FykITmgz17dPAhA5Ch1ax%2Fimage%20(1).png?alt=media&amp;token=2a807c4a-837e-4086-9fdb-ffb91b2963e0" alt="Webhook Details menu item"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Configure primary and optional secondary webhooks

The **Webhook Details** panel has two sections. Expand **Primary Webhook** or **Secondary Webhook** to edit each destination.

For each destination you can:

* Choose the **HTTP method** (`GET`, `POST`, or `PATCH`).
* Enter the **Webhook URL** where you want to receive order updates.
* Optionally set a **Secret Token** to secure requests to that destination.

The **primary webhook URL is required**. The secondary webhook is optional. If you add a secondary URL, it must be a valid `http` or `https` URL, and the secondary method and URL are saved together.

Click **Save Settings** to apply, or **Delete Settings** to remove the full configuration (primary and secondary).
{% endstep %}
{% endstepper %}

Once saved, Fincart sends updates to every configured destination whenever an order status changes.

{% hint style="info" %}
Each destination can use a different method, URL, and secret token. `POST` and `PATCH` requests include the JSON payload in the body. `GET` requests do not include a body — the destination must accept the request without one.
{% endhint %}

**Primary vs secondary webhook**

| Setting      | Primary                                  | Secondary                                         |
| ------------ | ---------------------------------------- | ------------------------------------------------- |
| Required     | Yes — URL is required to save            | No — leave empty if you only need one destination |
| HTTP method  | `GET`, `POST`, or `PATCH`                | `GET`, `POST`, or `PATCH`                         |
| Webhook URL  | Destination that always receives updates | Optional backup or second system                  |
| Secret token | Optional `Authorization` header value    | Optional, independent of the primary token        |
| Payload      | Same JSON payload                        | Same JSON payload                                 |

{% hint style="info" %}
Fincart calls the primary destination first, then the secondary if it is configured. Each call is independent: a failure or timeout on one destination does not prevent the other from being attempted.
{% endhint %}

**Webhook Payload Format**

When an order status update occurs, Fincart will send an HTTP request to each configured webhook URL with the following JSON payload:

```json
{
  "status": "processing",
  "subStatus": "out for delivery",
  "rejectionReason": null,
  "supportNote": "Customer requested a delay",
  "trackingNumber": "ARX123456XXX",
  "returnTrackingNumber": null,
  "statusUpdatedDate": 1738336796675, 
  "orderId": "67387ce18aa2230090e0XXXX", 
  "orderNumber": "ZZZ-DR-0013XXX",
  "courier": "J&T", 
  "courierLogo": "logo",
  "action": "Order Updated", 
  "invoiced": true,
  "invoicedAt": 1738336796675,
  "refNumber": "#1123"
}
```

`invoiced` and `invoicedAt` are returned only when the order is invoiced. `refNumber` is the order number in the merchant system (for example a Shopify order number).

**Field Details**

| Field                  | Type                | Description                                                                                                             |
| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `status`               | `string`            | The main order status (`pending`, `processing`, `successful`, `unsuccessful`, `cancelled`)                              |
| `subStatus`            | `string`            | The sub order status (`picked up`, `out for delivery`, `problematic`, etc.)                                             |
| `rejectionReason`      | `string` (nullable) | Reason for rejection if applicable (`no answer`, `rejected`, `reschedule`, etc.)                                        |
| `supportNote`          | `string` (nullable) | Additional notes related to the order update                                                                            |
| `trackingNumber`       | `string`            | The tracking number assigned to the order                                                                               |
| `returnTrackingNumber` | `string` (nullable) | If the order was returned and the courier generated a new tracking number, it will be provided here                     |
| `statusUpdatedDate`    | `number`            | The timestamp when the order status was updated                                                                         |
| `orderId`              | `string`            | Order ID at Fincart System                                                                                              |
| `orderNumber`          | `string`            | Order Number at Fincart System                                                                                          |
| `courier`              | `string`            | Courier Name                                                                                                            |
| `courierLogo`          | `string`            | Courier Logo                                                                                                            |
| `action`               | `string`            | `Order Updated` when order details changed but status did not, or `Order Status Changed` when the order status changed. |
| `invoiced`             | `boolean`           | Present with value `true` when the order is invoiced in Fincart                                                         |
| `invoicedAt`           | `number`            | The timestamp when the order got invoiced                                                                               |
| `refNumber`            | `string`            | Order ID at Merchant System                                                                                             |

**Order Status & Sub-Status Reference**

| Main Status    | Sub Status                               | Failed Attempt Reason | Order Type          |
| -------------- | ---------------------------------------- | --------------------- | ------------------- |
| `pending`      | `duplicate`                              |                       | Delivery            |
| `pending`      | `missing area`                           |                       | All                 |
| `pending`      | `missing tracking`                       |                       | All                 |
| `pending`      | `new`                                    |                       | Delivery / Exchange |
| `pending`      | `ready`                                  |                       | Return              |
| `processing`   | `picked up`                              |                       | Delivery / Exchange |
| `processing`   | `at courier hub`                         |                       | All                 |
| `processing`   | `out for delivery`                       |                       | Delivery / Exchange |
| `processing`   | `out for return`                         |                       | Return              |
| `processing`   | `out for exchange`                       |                       | Exchange            |
| `processing`   | `failed attempt`                         | `no answer`           | All                 |
| `processing`   | `failed attempt`                         | `reschedule`          | All                 |
| `processing`   | `failed attempt`                         | `rejected`            | All                 |
| `processing`   | `failed attempt`                         | `out of zone`         | All                 |
| `processing`   | `failed attempt`                         | `action required`     | All                 |
| `processing`   | `failed attempt`                         | `to be returned`      | Delivery / Exchange |
| `processing`   | `returned to courier`                    |                       | Return              |
| `processing`   | `exchanged & returned to courier`        |                       | Exchange            |
| `successful`   | `delivered to customer`                  |                       | Delivery            |
| `successful`   | `returned to merchant`                   |                       | Return              |
| `successful`   | `exchanged & returned to merchant`       |                       | Exchange            |
| `unsuccessful` | `delivery failed & returned to merchant` |                       | Delivery            |
| `unsuccessful` | `return failed`                          |                       | Return              |
| `unsuccessful` | `exchange failed & returned to merchant` |                       | Exchange            |
| `unsuccessful` | `problematic`                            |                       | All                 |
| `cancelled`    | `cancelled`                              |                       | All                 |

**Authentication & Security**

To ensure security, Fincart sends a **token** with every request when you configured a secret token for that destination. Validate the token for the destination that received the request before processing any data.

**Example Request Headers**

```json
{
  "Authorization": "{webhookToken}",
  "Content-Type": "application/json"
}
```

The primary webhook uses `webhook_token`. The secondary webhook uses `secondary_webhook_token` if one was saved. A destination with no token is called without an `Authorization` header.

**Merchant's Responsibility:**

1. **Validate the webhook token** for that destination before processing the request.
2. **Store the status updates** in your system.
3. **Handle failures gracefully** (e.g., retry logic for failed requests, ignore fields and statuses you don't expect).
4. If you use a secondary webhook, treat it as a second independent receiver of the same event — make processing **idempotent** so duplicate deliveries do not double-apply an update.

**Best Practices for Handling Webhooks**

✅ **Ensure every configured endpoint is available** to receive real-time updates.

✅ **Process webhook requests asynchronously** to avoid delays.

✅ **Implement logging & monitoring** for webhook failures on both destinations.
