Skip to main content

Digital Ordering API (2.0.0)

Download OpenAPI specification:Download

Contract for the Digital Ordering API — the API that connects a restaurant chain's POS / ordering back end to LoyaltyPlant's mobile-app ordering.

YOU (the vendor / POS integration) implement and host the five /rest/... endpoints below. LoyaltyPlant is the HTTP client: it calls your endpoints to fetch your menu, run a healthcheck, push orders, and poll order state. The only call that travels the other way is one webhook that you send to LoyaltyPlant when an order's status changes (modeled as the orderStatusWebhook callback on POST /rest/order). You never call LoyaltyPlant to create an order; LoyaltyPlant drives the flow by calling you.

Health

Availability probe LoyaltyPlant runs before sending orders.

Health check

LoyaltyPlant calls this before creating an order to confirm your integration and its downstream services are up. Return a flat JSON object mapping each service name you choose to its status (UP / DOWN). If any value is DOWN, LoyaltyPlant will not place an order at this outlet. No request body is sent.

Respond within ~5 s connect / 60 s read — LoyaltyPlant's client timeouts.

Authorizations:
AuthorizationToken
header Parameters
SalesOutletId
required
integer

Numeric id of the establishment this call targets. This is LoyaltyPlant's outlet id, not yours: LoyaltyPlant assigns it and gives it to you during onboarding. Resolve it to the correct venue/menu/configuration on your side. Sent on every LoyaltyPlant→vendor call and on the status webhook.

AuthorizationToken
required
string

Authentication token. For all Digital Ordering API calls this is the lowercase SHA-256 hex of the shared API key for the outlet (SHA256-hex(apiKey)), compared case-insensitively. On LoyaltyPlant→vendor requests, validate it against the key you hold for the SalesOutletId; on the order-status webhook you send the same hashed token. Example: "a3f5...e1" (64 lowercase hex chars).

Responses

Response samples

Content type
application/json
Example
{
  • "POS": "UP",
  • "DB": "UP",
  • "KITCHEN": "UP"
}

Menu

Menu retrieval and lightweight revision polling.

Get full menu

Returns the full menu for the outlet identified by SalesOutletId: categories, reusable modifier groups, the modifier pool, and items, plus a revision (epoch timestamp). LoyaltyPlant imports this and maps your ids to its own catalog. LoyaltyPlant typically calls GET /rest/menu/revision first and only calls this when the revision changed (see that operation). No request body.

The top-level object is wrapped under a menu key and also carries a requestId.

Respond within ~30 s connect / 180 s read — LoyaltyPlant's client timeouts.

Authorizations:
AuthorizationToken
header Parameters
SalesOutletId
required
integer

Numeric id of the establishment this call targets. This is LoyaltyPlant's outlet id, not yours: LoyaltyPlant assigns it and gives it to you during onboarding. Resolve it to the correct venue/menu/configuration on your side. Sent on every LoyaltyPlant→vendor call and on the status webhook.

AuthorizationToken
required
string

Authentication token. For all Digital Ordering API calls this is the lowercase SHA-256 hex of the shared API key for the outlet (SHA256-hex(apiKey)), compared case-insensitively. On LoyaltyPlant→vendor requests, validate it against the key you hold for the SalesOutletId; on the order-status webhook you send the same hashed token. Example: "a3f5...e1" (64 lowercase hex chars).

Responses

Response samples

Content type
application/json
{
  • "requestId": "f0c1a2b3-4d5e-6f70-8a9b-0c1d2e3f4a5b",
  • "menu": {
    }
}

Get menu revision

Returns just the current menu revision (an epoch timestamp), so LoyaltyPlant can cheaply decide whether to re-pull the full menu. It must equal the revision inside GET /rest/menu. LoyaltyPlant skips the full menu when the revision is unchanged, and re-pulls when it changed, when it has no cached value, or when the returned revision is lower than its cache. No request body.

Fail-open: if this pre-check fails for any reason, LoyaltyPlant falls back to a full GET /rest/menu.

Respond within ~30 s connect / 180 s read — LoyaltyPlant's client timeouts.

Authorizations:
AuthorizationToken
header Parameters
SalesOutletId
required
integer

Numeric id of the establishment this call targets. This is LoyaltyPlant's outlet id, not yours: LoyaltyPlant assigns it and gives it to you during onboarding. Resolve it to the correct venue/menu/configuration on your side. Sent on every LoyaltyPlant→vendor call and on the status webhook.

AuthorizationToken
required
string

Authentication token. For all Digital Ordering API calls this is the lowercase SHA-256 hex of the shared API key for the outlet (SHA256-hex(apiKey)), compared case-insensitively. On LoyaltyPlant→vendor requests, validate it against the key you hold for the SalesOutletId; on the order-status webhook you send the same hashed token. Example: "a3f5...e1" (64 lowercase hex chars).

Responses

Response samples

Content type
application/json
{
  • "revision": 1718280000
}

Orders

Order creation, order-state retrieval, and the order-status webhook.

Create order

LoyaltyPlant calls this to place a new order at your POS. The request is wrapped under an order key. Return the POS order id (posId) and the customer-facing queueNumber.

After the order is created, you notify LoyaltyPlant of every subsequent status change by POSTing the order-status webhook — see the orderStatusWebhook callback on this operation.

Reward items arrive in presents[]: the POS must charge 0 for them. Amounts are decimal strings/numbers; pan is masked when present.

Respond within ~5 s connect / 60 s read — LoyaltyPlant's client timeouts.

Authorizations:
AuthorizationToken
header Parameters
SalesOutletId
required
integer

Numeric id of the establishment this call targets. This is LoyaltyPlant's outlet id, not yours: LoyaltyPlant assigns it and gives it to you during onboarding. Resolve it to the correct venue/menu/configuration on your side. Sent on every LoyaltyPlant→vendor call and on the status webhook.

AuthorizationToken
required
string

Authentication token. For all Digital Ordering API calls this is the lowercase SHA-256 hex of the shared API key for the outlet (SHA256-hex(apiKey)), compared case-insensitively. On LoyaltyPlant→vendor requests, validate it against the key you hold for the SalesOutletId; on the order-status webhook you send the same hashed token. Example: "a3f5...e1" (64 lowercase hex chars).

X-LP-Webhook-Url
required
string <uri>

LoyaltyPlant's base URL for the order-status webhook callback. Sent by LoyaltyPlant on every createOrder call. The callback is posted to {X-LP-Webhook-Url}/digitalordering/pos/v2/integrated whenever an order's status changes.

Request Body schema: application/json
required
required
object (Order)

A Digital Ordering order. Used both as the createOrder request payload (inside CreateOrderRequest.order) and as the read model returned by getOrders (on reads, state, queueNumber, id and items are the meaningful fields). null fields are omitted from the wire.

Required-ness is direction-dependent and business-driven, so it is not expressed as schema required here; treat the expected set for each direction as required input regardless. On a createOrder request LoyaltyPlant always sends: type, deliveryAt, client (with name/email/phoneNumber), payment (with charge.tax/subtotal/total), additionalInfo, items; and address (with coordinates + addressString1) when type = DELIVERY. On a getOrders response only id, state and the line items are meaningful.

id
string

Direction-dependent. On a createOrder request this is LoyaltyPlant's order id (string). On a getOrders response (and on the status webhook) this is the posId you returned from createOrder — echo it back unchanged, because LoyaltyPlant keys the poll match on it.

object (Client)

The ordering customer. name, email and phoneNumber are required.

object (DeliveryAt)

When the order is wanted.

type
string (OrderingType)
Enum: "PICKUP" "DELIVERY" "EAT_IN" "CATERING" "DRIVE_THROUGH"

Fulfilment type of the order (the OrderingType enum on Order.type). Per-value meaning:

  • PICKUP: customer collects at the counter.
  • DELIVERY: courier delivery to address (address + coordinates required).
  • EAT_IN: dine-in.
  • CATERING: catering order. Code-backed but not shown in the public docs — documented; verify against POS model before relying on it.
  • DRIVE_THROUGH: drive-through pickup.

Note: For dine-in at a table, use EAT_IN with additionalInfo.tableNumber.

object

Delivery address. Required (with coordinates and addressString1) when type = DELIVERY; omitted otherwise.

comment
string

Free-text customer comment for the order.

queueNumber
string

Customer-facing queue / pickup number. Set by the POS and echoed on reads and webhooks; not sent by LoyaltyPlant on create.

object (PaymentInfo)

How the order is paid and the charge breakdown.

object

Order state. Present on getOrders responses (and pushed via the webhook); not sent on createOrder.

object (AdditionalInfo)

Order metadata.

Array of objects (OrderItem)

Reward (free) items granted by the loyalty program. The POS must charge 0 for these — they are not paid by the customer.

Array of objects (OrderItem)

Paid order line items. Each id maps to a menu item id.

Responses

Callbacks

Request samples

Content type
application/json
Example
{
  • "order": {
    }
}

Response samples

Content type
application/json
Example
{
  • "posId": "POS-9F3A21",
  • "queueNumber": "A17"
}

Callback payload samples

Callback
POST: Push order status to LoyaltyPlant (vendor → LoyaltyPlant)
Content type
application/json
Example
{
  • "orders": [
    ]
}

Get orders by POS id

Returns the current state of one or more orders, looked up by the POS ids you returned from createOrder. It is a read, expressed as POST because the id list travels in the request body (wrapped under orderPosIds). LoyaltyPlant uses it to poll / reconcile order lifecycle when a webhook was missed.

Each returned order carries its state.status (one of the nine OrderStatus values); state.reason is required when the status is CANCELED or FAILED, and an optional structured state.posErrorType may accompany it (see the PosErrorType enum).

Respond within ~5 s connect / 60 s read — LoyaltyPlant's client timeouts.

Authorizations:
AuthorizationToken
header Parameters
SalesOutletId
required
integer

Numeric id of the establishment this call targets. This is LoyaltyPlant's outlet id, not yours: LoyaltyPlant assigns it and gives it to you during onboarding. Resolve it to the correct venue/menu/configuration on your side. Sent on every LoyaltyPlant→vendor call and on the status webhook.

AuthorizationToken
required
string

Authentication token. For all Digital Ordering API calls this is the lowercase SHA-256 hex of the shared API key for the outlet (SHA256-hex(apiKey)), compared case-insensitively. On LoyaltyPlant→vendor requests, validate it against the key you hold for the SalesOutletId; on the order-status webhook you send the same hashed token. Example: "a3f5...e1" (64 lowercase hex chars).

Request Body schema: application/json
required
orderPosIds
required
Array of strings

POS order ids (the posId values you returned from createOrder) to look up.

Responses

Request samples

Content type
application/json
{
  • "orderPosIds": [
    ]
}

Response samples

Content type
application/json
Example
{
  • "requestId": "7e9c2a14-3b6d-4f80-91ac-5d2e6f7a8b90",
  • "orders": [
    ]
}