Next Restaurant 6.1.0: move your data in, run payroll, and connect other systems Next Inventory 6.2.0: a REST API and webhooks for your other systems Next DB 6.1: Auto-Updating Tables, Printing, Phone Layout and SEO Next Task 6.0.0: a task manager for Joomla Next Inventory 6.1.1: smoother Check Out, no more list limits, and much faster PHP2Shell: Is Your Joomla Site Safe? What to Do Today Introducing Next Boards: Kanban project and task boards for Joomla Building the Future of Joomla Extensions
NextSoftware

Create Order

POST /v1/nextrestaurant/orders

Place an order

Creates an ordinary order: it routes to kitchen stations by your routing rules, depletes stock at the status you configured, settles into the payments ledger, and appears in reports with its channel recorded.

Orders arrive unpaid — this endpoint records an order, it does not take payment.

Needs orders:write and the Orders app. Open in demo mode, like the storefront. Send an Idempotency-Key so a retry after a timeout cannot create a second order. Also limited to 60 orders per 5 minutes per address.

Request

POST https://your-site.example/api/index.php/v1/nextrestaurant/orders

Parameters

Name Type In Required Description
Idempotency-Key string header No Any unique string up to 255 characters, e.g. a UUID. Send the same key when retrying after a timeout: the first response is replayed (with Idempotent-Replayed: true) and nothing happens twice. Reusing a key for a different request is 422 IDEMPOTENCY_MISMATCH; while the first request is still running it is 409 IDEMPOTENCY_IN_PROGRESS. Keys are kept 24 hours, per API key. (max length 255)

Request body

Content type: application/json

Field Type Required Description
location_id integer Yes Where the order is placed. (int64)
items object[] Yes
items.item_id integer Yes (int64)
items.qty number Yes
items.variation_id integer|null No Required in practice whenever the item has variations. (int64)
items.notes string No
items.modifiers object[] No
items.modifiers.modifier_id integer Yes (int64)
items.modifiers.qty integer No Defaults to 1.
channel string No Recorded on the order and visible in reports. Any other value falls back to web rather than being refused. One of web, phone, takeaway, delivery. Defaults to web.
service_mode string No Free text stored with the order.
notes string No Order-level note, shown to the kitchen.
customer object No Guest details stored with the order. Every field optional.
customer.name string No
customer.phone string No
customer.email string No (email)
{
    "location_id": 2,
    "channel": "web",
    "service_mode": "takeaway",
    "notes": "Ring the bell at the side door",
    "customer": {
        "name": "Dana Whitfield",
        "phone": "+1 555 0142",
        "email": "[email protected]"
    },
    "items": [
        {
            "item_id": 16,
            "variation_id": 2,
            "qty": 1,
            "notes": "Well done",
            "modifiers": [
                {
                    "modifier_id": 5,
                    "qty": 1
                }
            ]
        },
        {
            "item_id": 1,
            "qty": 2
        }
    ]
}

Responses

201 — The order was created.

{
    "data": {
        "id": 591,
        "order_number": "ORD-000591",
        "location_id": 2,
        "channel": "web",
        "status": "placed",
        "fulfillment_status": "in_kitchen",
        "subtotal": 18.5,
        "discount_total": 0,
        "tax_total": 1.53,
        "service_charge": 0,
        "delivery_fee": 0,
        "grand_total": 20.03,
        "currency": null,
        "notes": null,
        "placed_at": "2026-09-07 21:20:26",
        "updated_at": "2026-09-07 21:20:26",
        "payments": [],
        "items": [
            {
                "id": 1300,
                "item_id": 16,
                "variation_id": 2,
                "name_snapshot": "Margherita Pizza (Large)",
                "qty": 1,
                "unit_price": 17,
                "modifiers_total": 1.5,
                "line_total": 18.5,
                "notes": null
            }
        ]
    }
}
Field Type Meaning
data object An order with its lines and payments — the same object GET /orders/{id} returns and every order.* webhook carries as data. Datetimes are Y-m-d H:i:s in UTC with no zone suffix.
data.id integer (int64)
data.order_number string|null
data.location_id integer (int64)
data.customer_id integer|null
data.table_id integer|null
data.channel string|null
data.source string|null Where an online order came from (web, qr, api); null for staff-entered orders.
data.status string placed on creation; then confirmed, preparing, ready, served, completed, cancelled or refunded.
data.fulfillment_status string|null
data.guest_count integer|null
data.subtotal number
data.discount_total number
data.tax_total number
data.service_charge number
data.tip_total number
data.delivery_fee number
data.grand_total number
data.currency string|null Often null — take the currency from the location.
data.notes string|null
data.scheduled_for string|null
data.placed_at string|null
data.completed_at string|null
data.cancelled_at string|null
data.cancel_reason string|null
data.created_at string|null
data.updated_at string|null
data.items[].id integer (int64)
data.items[].item_id integer (int64)
data.items[].variation_id integer|null (int64)
data.items[].name_snapshot string The line as the kitchen and the receipt will show it, including the variation.
data.items[].qty number
data.items[].unit_price number Resolved from the catalogue. A submitted price is ignored.
data.items[].modifiers_total number
data.items[].discount_amount number
data.items[].line_total number
data.items[].status string|null
data.items[].seat_number integer|null
data.items[].notes string|null
data.payments[].id integer (int64)
data.payments[].order_id integer|null
data.payments[].location_id integer|null
data.payments[].method string|null
data.payments[].amount number
data.payments[].tip_amount number
data.payments[].refunded_total number Sum of the refunds against this payment.
data.payments[].currency string|null
data.payments[].status string
data.payments[].reference string|null The provider's or the till's transaction reference.
data.payments[].paid_at string|null
data.payments[].created_at string|null
data.payments[].updated_at string|null

Errors

Status Code When
400 INVALID_ORDER One of the items is no longer available.
401 INVALID_TOKEN The token is missing, wrong, or none has been generated.
403 INSUFFICIENT_SCOPE This API key does not have the permission this request needs.
403 MODULE_DISABLED This module is disabled.
403 API_DISABLED API is disabled
404 UNKNOWN_LOCATION No such published location.
429 RATE_LIMITED Too many requests. RATE_LIMITED with a Retry-After header: this key used its budget for the minute, or this address sent 20 bad tokens in 5 minutes. Nothing ran, so the request is safe to retry after the wait.
500 ORDER_FAILED The order could not be created. The message is deliberately generic; the detail is in the Joomla log under administrator/logs/.

Examples

curl

curl -s -X POST "https://your-site.example/api/index.php/v1/nextrestaurant/orders" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"location_id":2,"channel":"web","service_mode":"takeaway","notes":"Ring the bell at the side door","customer":{"name":"Dana Whitfield","phone":"+1 555 0142","email":"[email protected]"},"items":[{"item_id":16,"variation_id":2,"qty":1,"notes":"Well done","modifiers":[{"modifier_id":5,"qty":1}]},{"item_id":1,"qty":2}]}'

PHP

<?php
$ch = curl_init('https://your-site.example/api/index.php/v1/nextrestaurant/orders');

curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => '{"location_id":2,"channel":"web","service_mode":"takeaway","notes":"Ring the bell at the side door","customer":{"name":"Dana Whitfield","phone":"+1 555 0142","email":"[email protected]"},"items":[{"item_id":16,"variation_id":2,"qty":1,"notes":"Well done","modifiers":[{"modifier_id":5,"qty":1}]},{"item_id":1,"qty":2}]}',
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

JavaScript

const API_TOKEN = process.env.API_TOKEN;

const response = await fetch("https://your-site.example/api/index.php/v1/nextrestaurant/orders", {
  method: 'POST',
  headers: {
    "Authorization": `Bearer ${API_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "location_id": 2,
    "channel": "web",
    "service_mode": "takeaway",
    "notes": "Ring the bell at the side door",
    "customer": {
      "name": "Dana Whitfield",
      "phone": "+1 555 0142",
      "email": "[email protected]"
    },
    "items": [
      {
        "item_id": 16,
        "variation_id": 2,
        "qty": 1,
        "notes": "Well done",
        "modifiers": [
          {
            "modifier_id": 5,
            "qty": 1
          }
        ]
      },
      {
        "item_id": 1,
        "qty": 2
      }
    ]
  }),
});
const data = await response.json();

All Extensions