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

# Webhooks

> What Lojou sends to your configured URL, and when.

After you register a webhook (`POST /v1/webhooks`), Lojou makes a `POST` request with a JSON payload to your URL whenever one of the configured events happens. This saves you from having to poll `GET /v1/orders/{id}` to find out when an order's status changed.

## Available events

| Event             | Fires when                                                                                                                                                                                               |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `order_approved`  | An order's payment was confirmed.                                                                                                                                                                        |
| `order_cancelled` | A payment attempt failed or was cancelled.                                                                                                                                                               |
| `order_refund`    | Shows up as an option when creating a webhook from the dashboard, but **nothing in the current codebase actually fires it yet** — no refund flow triggers this webhook today. Don't rely on it arriving. |

Pick the events via the `events` field when creating the webhook (`POST /v1/webhooks`).

## Scoping to a product

A webhook can be filtered to a single product (set `product_details` when creating it) or fire for **any** product in the store (leave `product_details` out). If you have more than one webhook registered for the same URL, Lojou groups them and sends a single delivery per URL — it won't duplicate.

## The payload

```json theme={null}
{
  "order_type": "order_approved",
  "order_number": "95428522",
  "status": "approved",
  "transaction_id": "T821671018874668",
  "payment_method": "card",
  "amount": 748.6,
  "currency": "MZN",
  "discount_amount": 0,
  "coupon_code": null,
  "original_amount": 748.6,
  "tracking": {
    "utm_source": "facebook",
    "utm_campaign": "launch",
    "utm_medium": null,
    "utm_content": null,
    "utm_term": null
  },
  "plan_subscriber": {
    "plan_name": null,
    "start_date": null,
    "end_date": null,
    "status": null,
    "plan_type": null,
    "plan_interval": null,
    "cancelled_at": null,
    "portal_url": "https://pay.lojou.app/order/95428522?transaction_id=T821671018874668"
  },
  "product": {
    "name": "Spy App",
    "price": "778.05",
    "pid": "QUyMp"
  },
  "customer": {
    "email": "maphate.tshepo77@gmail.com",
    "name": "Tshepo Joshua",
    "mobile_number": "+270637423882",
    "payment_number": null
  },
  "affiliate": [],
  "order_bump": [],
  "brand": "Lojou",
  "image": "https://api.lojou.app/assets/lojou-2.png"
}
```

`plan_subscriber` is only actually populated for `recurring` products (subscriptions) — for `one_time` products those fields come back `null`, except `portal_url`, which is always built.

## Delivery — what to expect

* **No signature/cryptographic verification.** Lojou doesn't currently send any `X-Lojou-Signature`-style header to prove the payload's origin. Treat your endpoint URL as something only you know, and validate the content (e.g. confirm the `order_number` via `GET /v1/orders/{id}`) before acting on it for anything sensitive.
* **No automatic retries.** It's a single `POST` attempt with a 10s timeout — if your endpoint is down or too slow, that specific delivery is lost (it's only recorded as a failure in the webhook's report; `GET /v1/webhooks/{id}` shows the summary). If you need delivery guarantees, treat webhooks as a "something changed" nudge and confirm with a `GET /v1/orders/{id}` call afterward.
* **Respond fast, with a `2xx`.** Anything outside the `2xx` range counts as a failure in the webhook report, even if you already processed the event.

## Debugging

`GET /v1/webhooks/{id}` returns a `summary` with the timestamp and status of the last delivery. To see the exact payload sent on a specific attempt and what your endpoint responded, that's still only available from the Lojou dashboard (Settings → Webhooks → Reports) — not yet exposed through the public API.
