# Webhooks

## Webhooks API Documentation

### Introduction

Welcome to the Ayor Webhook API documentation. This guide helps third-party developers integrate with our webhook system to receive real-time event notifications securely and reliably.

***

### Webhook Overview

Webhooks allow your system to receive automated event notifications (such as `order.created`) from Ayor. They are delivered as HTTPS POST requests to your specified endpoint. Events are pushed using Google Pub/Sub.

***

### Event Types

You can subscribe to the following event types:

* `order.created` <i class="fa-check">:check:</i>       &#x20;
* `order.updated` <i class="fa-check">:check:</i>
* `order.confirmed` <i class="fa-clock">:clock:</i>
* `order.shipped` <i class="fa-clock">:clock:</i>
* `order.delivered` <i class="fa-clock">:clock:</i>
* `order.cancelled` <i class="fa-clock">:clock:</i>
* `product.out_of_stock` <i class="fa-clock">:clock:</i>
* `subscription.renewed` <i class="fa-clock">:clock:</i>
* `subscription.expired` <i class="fa-clock">:clock:</i>
* `integration.failed` <i class="fa-clock">:clock:</i>
* `domain.connected` <i class="fa-clock">:clock:</i>

***

### Integration Guide

#### Payload Format

Each webhook event is delivered as a Pub/Sub message structured like this:

```json
{
  "deliveryAttempt": 1,
  "message": {
    "attributes": {
      "event_id": "<uuid>",
      "event_type": "order.created",
      "shop_id": "<uuid>",
      "timestamp": "2025-08-06T15:35:30.491494",
      "user_id": "<id>"
    },
    "data": "<base64-encoded-payload>"
  },
  "subscription": "projects/.../subscriptions/webhook-<user_id>-<event_type>-<hash>"
}
```

#### Decoded Payload Example

The `data` field contains a base64-encoded JSON object. After decoding, here is a sample payload for `order.created`:

```json
{
  "event_id": "77d13351-0578-4f6f-ba5e-fb38405b75ba",
  "event_type": "order.created",
  "user_id": "2734",
  "timestamp": "2025-08-18T10:19:43.760875Z",
  "data": {
    "event_id": "77d13351-0578-4f6f-ba5e-fb38405b75ba",
    "order_id": "10e0e5ff-c844-4ad8-80f5-7024c5df8d39",
    "display_id": 33,
    "confirmation_status": "Pending",
    "delivery_status": null,
    "total_price": 1800,
    "delivery_price": 0,
    "currency": "DZD",
    "payment_method": "cod",
    "payment_status": "pending",
    "is_stop_desk": false,
    "shipping_id": null,
    "client_note": null,
    "created_at": "2025-08-18T10:19:39.680686+00:00",
    "updated_at": "2025-08-18T10:19:39.817185+00:00",
    "client_info": {
      "full_name": "Touares tou",
      "phone_number": "0770707070",
      "email": null,
      "state": "12 - Tébessa - تبسة",
      "city": "بئر العاتر"
    },
    "custom_fields": [
    {
      "field_id": 6,
      "field_name": "Custom",
      "custom_title": "Custom Address",
      "value": "sdfghjk",
      "item_id": null
    }
    ],
    "timestamp": "2025-08-18T10:19:43.757867",
    "order_lines": [
      {
        "product_id": "b26bca7a-35cd-4397-bb5d-c5708a22c58c",
        "product_name": "Aqua di Gio",
        "variant_name": null,
        "quantity": 1,
        "unit_price": 1800,
        "reduced_price": null,
        "total_price": 1800,
        "sku": null,
        "shipping_id": null
      }
    ],
    "bundle_lines": [],
    "shop_info": {
      "shop_id": "52f9c4ea-7cbe-4b32-9696-99e9f32c5daf",
      "shop_name": "store",
      "shop_subdomain": "store"
    },
    "landing_page_info": {
      "landing_page_id": "f29039b5-b670-438a-acd0-c5e88aea5b9a",
      "landing_page_title": "Aqua di Gio"
    }
  }
}
```

#### Payload Schema (Field Reference)

Each event includes a JSON payload with the following fields:

| Field                 | Type                |                    Required                   | Description                                        | Allowed Values                                                           |
| --------------------- | ------------------- | :-------------------------------------------: | -------------------------------------------------- | ------------------------------------------------------------------------ |
| `event_id`            | `string`            | <i class="fa-square-check">:square-check:</i> | Unique identifier of the event                     |                                                                          |
| `event_type`          | `string`            | <i class="fa-square-check">:square-check:</i> | Type of event (e.g., `order.created`)              |                                                                          |
| `user_id`             | `string`            | <i class="fa-square-check">:square-check:</i> | ID of the user (merchant)                          |                                                                          |
| `timestamp`           | `string (ISO 8601)` | <i class="fa-square-check">:square-check:</i> | Time the event was generated                       |                                                                          |
| `order_id`            | `string`            | <i class="fa-square-check">:square-check:</i> | Unique ID of the order                             |                                                                          |
| `display_id`          | `integer`           | <i class="fa-square-check">:square-check:</i> | Merchant-facing order reference number             |                                                                          |
| `confirmation_status` | `string`            | <i class="fa-square-check">:square-check:</i> | Status of order confirmation                       | `Pending`, `Confirmed`, `Callback`, `Cancelled`                          |
| `delivery_status`     | `string or null`    |     <i class="fa-square-x">:square-x:</i>     | Status of delivery, if available                   | `CREATED`, `IN_TRANSIT`, `PENDING`, `DELIVERED`, `CANCELLED`, `RETURNED` |
| `total_price`         | `decimal`           | <i class="fa-square-check">:square-check:</i> | Total order amount including products and delivery |                                                                          |
| `delivery_price`      | `decimal`           | <i class="fa-square-check">:square-check:</i> | Delivery fee                                       |                                                                          |
| `currency`            | `string`            | <i class="fa-square-check">:square-check:</i> | Currency code (e.g., DZD)                          |                                                                          |
| `payment_method`      | `string`            | <i class="fa-square-check">:square-check:</i> | Payment method used                                | `cod`, `stripe`                                                          |
| `payment_status`      | `string`            | <i class="fa-square-check">:square-check:</i> | Status of the payment                              | `pending`, `completed`, `failed`                                         |
| `is_stop_desk`        | `boolean`           | <i class="fa-square-check">:square-check:</i> | Whether the order is a stop-desk pickup            |                                                                          |
| `shipping_id`         | `string or null`    |     <i class="fa-square-x">:square-x:</i>     | Shipping provider ID or tracking ref               |                                                                          |
| `client_note`         | `string or null`    |     <i class="fa-square-x">:square-x:</i>     | Customer-provided message                          |                                                                          |
| `created_at`          | `string (ISO 8601)` | <i class="fa-square-check">:square-check:</i> | Timestamp of order creation                        |                                                                          |
| `updated_at`          | `string (ISO 8601)` | <i class="fa-square-check">:square-check:</i> | Timestamp of last update to the order              |                                                                          |

**`client_info` object**

| Field          | Type             |                    Required                   | Description           |
| -------------- | ---------------- | :-------------------------------------------: | --------------------- |
| `full_name`    | `string`         | <i class="fa-square-check">:square-check:</i> | Customer full name    |
| `phone_number` | `string`         | <i class="fa-square-check">:square-check:</i> | Customer phone number |
| `email`        | `string or null` |     <i class="fa-square-x">:square-x:</i>     | Customer email        |
| `state`        | `string`         | <i class="fa-square-check">:square-check:</i> | Customer state/region |
| `city`         | `string`         | <i class="fa-square-check">:square-check:</i> | Customer city         |

**`custom_fields` array**

Each field added by the merchant to their landing page:

| Field          | Type             |                    Required                   | Description                          |
| -------------- | ---------------- | :-------------------------------------------: | ------------------------------------ |
| `field_id`     | `integer`        | <i class="fa-square-check">:square-check:</i> | ID of the custom form field          |
| `field_name`   | `string`         | <i class="fa-square-check">:square-check:</i> | Name of the custom field             |
| `custom_title` | `string`         |     <i class="fa-square-x">:square-x:</i>     | Label used on the landing page       |
| `value`        | `string`         | <i class="fa-square-check">:square-check:</i> | Submitted value                      |
| `item_id`      | `string or null` |     <i class="fa-square-x">:square-x:</i>     | Internal reference to the form entry |

**`order_lines` array**

One entry per product ordered:

| Field           | Type              |                    Required                   | Description                                       |
| --------------- | ----------------- | :-------------------------------------------: | ------------------------------------------------- |
| `product_id`    | `string`          | <i class="fa-square-check">:square-check:</i> | ID of the product ordered                         |
| `product_name`  | `string`          | <i class="fa-square-check">:square-check:</i> | Name of the product variant                       |
| `variant_name`  | `string`          | <i class="fa-square-check">:square-check:</i> | Variant description (e.g., size, color)           |
| `quantity`      | `integer`         | <i class="fa-square-check">:square-check:</i> | Number of units ordered                           |
| `unit_price`    | `decimal`         | <i class="fa-square-check">:square-check:</i> | Price per unit                                    |
| `reduced_price` | `decimal or null` |     <i class="fa-square-x">:square-x:</i>     | Discounted price if applicable                    |
| `total_price`   | `decimal`         | <i class="fa-square-check">:square-check:</i> | Final price (unit × quantity or discounted total) |
| `sku`           | `string`          | <i class="fa-square-check">:square-check:</i> | Product SKU                                       |
| `shipping_id`   | `string or null`  |     <i class="fa-square-x">:square-x:</i>     | Product-specific shipping ID                      |

**`bundle_lines` array**

Empty array if no bundles were ordered.

**`shop_info` object**

| Field            | Type     |                    Required                   | Description       |
| ---------------- | -------- | :-------------------------------------------: | ----------------- |
| `shop_id`        | `string` | <i class="fa-square-check">:square-check:</i> | Unique shop ID    |
| `shop_name`      | `string` | <i class="fa-square-check">:square-check:</i> | Store name        |
| `shop_subdomain` | `string` | <i class="fa-square-check">:square-check:</i> | Store’s subdomain |

**`landing_page_info` object**

| Field                | Type     |                    Required                   | Description                     |
| -------------------- | -------- | :-------------------------------------------: | ------------------------------- |
| `landing_page_id`    | `string` | <i class="fa-square-check">:square-check:</i> | ID of the landing page          |
| `landing_page_title` | `string` | <i class="fa-square-check">:square-check:</i> | Title shown on the landing page |

***

### **Retry Behavior**

* If your endpoint responds with a non-`2xx` status or times out, we retry the request using **exponential backoff**:
  * 1st retry: \~5 seconds after failure
  * Subsequent retries: delay doubles each time, up to 5 minutes between attempts
* Each message is retried up to **5 times**.
* If all retries fail, the message is sent to a **Dead Letter Queue (DLQ)** and will not be redelivered automatically.

***

### Best Practices

* **Respond quickly** (<30s) with HTTP 2xx
* **Process asynchronously** — don't block on business logic
* **Verify signature** for authenticity
* **Use `event_id`** to ensure idempotency
* **Expect retries** and duplicate deliveries

***

### Support

For technical support, contact: <support@ayor.ai> - <ali@ayor.ai><br>

***

*Last updated: August 7, 2025*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ayor.gitbook.io/ayor-docs/webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
