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

# Create An Aggregator Order

> Create a validated delivery, pickup, dine-in, or drive-through order in Plato.

Creates one order in the API key workspace and broadcasts it to Plato POS and KDS.

## Request

```bash theme={null}
curl "https://api.plato.ae/api/v1/aggregators/orders" \
  -X POST \
  -H "Authorization: Bearer $PLATO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: talabat-TLB-84721" \
  -H "X-Request-Id: my-trace-84721" \
  -d '{
    "externalOrderId": "TLB-84721",
    "type": "talabat",
    "paymentStatus": "PAID",
    "placedAt": "2026-07-28T16:30:00+04:00",
    "customer": {
      "name": "Jane Customer",
      "phone": "+971501234567",
      "email": "jane@example.com"
    },
    "deliveryAddress": {
      "addressLine1": "Building 10, Sheikh Zayed Road",
      "addressLine2": "Apartment 1204",
      "city": "Dubai",
      "country": "United Arab Emirates",
      "latitude": 25.2048,
      "longitude": 55.2708,
      "additionalInfo": "Call on arrival"
    },
    "items": [
      {
        "externalId": "item-100",
        "sku": "BURGER-01",
        "name": "Classic Burger",
        "quantity": 2,
        "unitPrice": 25,
        "totalPrice": 50,
        "notes": "No onions",
        "modifiers": [
          {
            "externalId": "mod-10",
            "name": "Extra cheese",
            "quantity": 2,
            "unitPrice": 0
          }
        ]
      },
      {
        "externalId": "item-200",
        "sku": "FRIES-01",
        "name": "French Fries",
        "quantity": 1,
        "unitPrice": 12,
        "totalPrice": 12
      }
    ],
    "pricing": {
      "subtotal": 62,
      "deliveryFee": 5,
      "discount": 4.5,
      "charges": [
        {
          "externalId": "service-fee",
          "name": "Service fee",
          "amount": 2.5
        }
      ],
      "vatRate": 5,
      "isVatInclusive": true,
      "total": 65,
      "currency": "AED"
    },
    "notes": "Leave at reception"
  }'
```

## Top-Level Fields

| Field             | Type     | Required     | Notes                                                                                                      |
| ----------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------- |
| `type`            | string   | Yes          | Aggregator identifier such as `talabat` or `noon_food`.                                                    |
| `externalOrderId` | string   | Yes          | Unique order id in the aggregator. Maximum 160 characters.                                                 |
| `paymentStatus`   | enum     | No           | Defaults to `UNPAID`. `PAID` creates a succeeded incoming payment for the full order total.                |
| `customer`        | object   | No           | When supplied, include at least a name, phone, or email. Existing customers are matched by phone or email. |
| `deliveryAddress` | object   | For delivery | Required only when `type` is the native `DELIVERY` value.                                                  |
| `items`           | array    | Yes          | Between 1 and 250 items.                                                                                   |
| `pricing`         | object   | Yes          | Trusted order totals and currency.                                                                         |
| `notes`           | string   | No           | Restaurant-facing order note. Maximum 2,000 characters.                                                    |
| `placedAt`        | ISO 8601 | No           | When the customer placed the order, including a UTC offset.                                                |
| `scheduledFor`    | ISO 8601 | No           | Desired preparation or fulfillment time, including a UTC offset.                                           |

## Item Fields

| Field            | Type   | Required | Notes                                                                       |
| ---------------- | ------ | -------- | --------------------------------------------------------------------------- |
| `name`           | string | Yes      | Customer-visible product name.                                              |
| `quantity`       | number | Yes      | Must be greater than zero.                                                  |
| `unitPrice`      | number | Yes      | Final per-unit item price.                                                  |
| `totalPrice`     | number | No       | Defaults to `quantity × unitPrice` and must match it when supplied.         |
| `externalId`     | string | No       | Product or line id in the aggregator.                                       |
| `sku`            | string | No       | Aggregator catalog SKU.                                                     |
| `platoProductId` | string | No       | Optional Plato product identifier stored with the submitted item snapshot.  |
| `notes`          | string | No       | Kitchen-facing item note.                                                   |
| `modifiers`      | array  | No       | Modifier snapshots with name, quantity, unit price, total, and external id. |

`unitPrice` should already include any modifier amount represented in the line total. Modifiers are stored as a preparation snapshot and are not added to `pricing.subtotal` a second time.

## Optional Customer Information

The entire `customer` object is optional. This is valid for orders where the aggregator does not share customer details.

If `customer` is included, provide at least one of `name`, `phone`, or `email`. Plato uses phone or email to match an existing customer when available.

`deliveryAddress` is separate from `customer` and remains required for `DELIVERY` orders.

## Noon Food Pickup Example

This smaller request creates a pickup order without customer information:

```json theme={null}
{
  "type": "noon_food",
  "externalOrderId": "NF-529104",
  "paymentStatus": "PAID",
  "items": [
    {
      "externalId": "NF-ITEM-77",
      "name": "Chicken Shawarma",
      "quantity": 1,
      "unitPrice": 22,
      "totalPrice": 22
    }
  ],
  "pricing": {
    "subtotal": 22,
    "total": 22,
    "currency": "AED"
  }
}
```

## Pricing Fields

| Field            | Type    | Required | Notes                                                        |
| ---------------- | ------- | -------- | ------------------------------------------------------------ |
| `subtotal`       | number  | Yes      | Sum of item totals before order-level fees and discount.     |
| `deliveryFee`    | number  | No       | Defaults to `0`.                                             |
| `discount`       | number  | No       | Fixed order-level discount. Defaults to `0`.                 |
| `charges`        | array   | No       | Fixed service, packaging, or marketplace charges.            |
| `vatRate`        | number  | No       | Percentage from `0` to `100`. Defaults to `0`.               |
| `isVatInclusive` | boolean | No       | Defaults to `true`. When false, VAT is added to the total.   |
| `total`          | number  | Yes      | Final customer total after fees, charges, discount, and VAT. |
| `currency`       | string  | No       | Three-letter uppercase code. Defaults to `AED`.              |

## Created Response

A new order returns `201 Created`:

```json theme={null}
{
  "data": {
    "id": "cm_order_123",
    "externalOrderId": "TLB-84721",
    "appSlug": "talabat",
    "type": "PICK_UP",
    "referenceNumber": 1043,
    "status": "PENDING",
    "paymentStatus": "PAID",
    "total": 65,
    "currency": "AED",
    "payment": {
      "id": "cm_payment_123",
      "method": "OTHER",
      "status": "succeeded",
      "amount": 65,
      "totalAmount": 65,
      "currency": "AED"
    },
    "createdAt": "2026-07-28T12:30:03.120Z"
  },
  "meta": {
    "idempotentReplay": false,
    "requestId": "my-trace-84721"
  }
}
```

The response includes:

* `X-Request-Id`, which echoes your request id or contains one generated by Plato.
* `meta.idempotentReplay`, which is `false` for a new order and `true` for a safe retry.

## What Plato Creates

Plato creates the order and item snapshots using the submitted pricing and aggregator metadata. When customer information is provided, Plato finds or creates the customer and connects it to the order.

When `paymentStatus` is `PAID`, Plato also creates a succeeded `IN` payment linked to the order. Its amount and total equal `pricing.total`, its currency matches `pricing.currency`, and its method is `OTHER` for an externally collected aggregator payment. Safe retries return the same payment instead of creating another one.

For aggregator types, Plato saves `PICK_UP` as the POS fulfillment type and sets the matching `appSlug` automatically. The POS therefore displays the aggregator name and icon. If the app is not installed in the workspace, Plato returns an error without creating the order.

The order always starts as `PENDING`; an aggregator cannot inject an accepted or completed order through this endpoint.
