<!-- canonical: https://docs.costplus.io/api-reference/webhooks -->

> Payload formats for Cost+ webhook notifications
Cost+ sends webhook notifications to your configured `webhook_url` when order or transaction statuses change. This page documents the event payload formats.

For webhook configuration, retry logic, and best practices, see the [Webhooks guide](/docs/guides/webhooks).

## OrderStatusChangedEvent

Sent when an order's status changes (e.g., from `new` to `completed`).

```json title="Example payload"
{
  "event": "status_changed",
  "project_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "order_id": "b9ae6d70-1234-5678-9abc-def012345678"
}
```

| Field | Type | Description |
|---|---|---|
| `event` | string | Always `"status_changed"` |
| `project_id` | string (UUID) | The project this order belongs to |
| `order_id` | string (UUID) | The order whose status changed |

> [!WARNING]
> The webhook payload only contains the order ID — **not** the new status. Always verify the current status by calling [Get Order](/api-reference/orders/getOrder) before taking action (e.g., shipping goods or granting access).

## TransactionStatusChangedEvent

Sent when an individual transaction's status changes within an order.

```json title="Example payload"
{
  "event": "transaction_status_changed",
  "merchant_id": "f1e2d3c4-b5a6-7890-fedc-ba0987654321",
  "project_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "order_id": "b9ae6d70-1234-5678-9abc-def012345678",
  "transaction_id": "c8d7e6f5-4321-0987-6543-210fedcba098",
  "transaction_status": "completed"
}
```

| Field | Type | Description |
|---|---|---|
| `event` | string | Always `"transaction_status_changed"` |
| `merchant_id` | string (UUID) | Your merchant identifier |
| `project_id` | string (UUID) | The project this order belongs to |
| `order_id` | string (UUID) | The parent order |
| `transaction_id` | string (UUID) | The specific transaction whose status changed |
| `transaction_status` | string | New status: `new`, `pending`, `processing`, `accepted`, `captured`, `completed`, `cancelled`, `error`, or `expired` |

## Delivery & Retries

- Cost+ retries up to **10 times**, spaced **2 minutes apart**
- First attempt times out after **4 seconds**; subsequent retries after **10 seconds**
- Your endpoint must return a **2xx** status code to acknowledge receipt
- If all 10 retries fail, the event is marked as failed

## Webhook URL Configuration

You can set the webhook URL in two ways:

1. **Per order** — include `webhook_url` in the [Create Order](/api-reference/orders/createOrder) request
2. **Project-level** — configure a default webhook URL in the [Merchant Portal](https://dashboard.costplus.io/) under your website settings
