External Order API
The External Order API accepts a fully-formed order from any external system — a delivery aggregator, a white-label app, a kiosk, a voice agent — and routes it into the running APRO POS at the target location. A single POST is enough; the order appears on the order-manager screen immediately.
- Endpoint:
POST https://my.apro.at/api/v1/external/order - Auth: API key in
x-api-key - Content type:
application/json
Routing the order to a location
The order must be addressable to one concrete location. Provide one of the following — the first that is non-null wins:
LocationID— numeric IDLocationShortCode— short string identifier (e.g.vienna-main)SpotID— a specific table/room/pickup spot (location is derived)QRCode— a scanned APRO QR code (location and spot are derived)
If none is provided, the request is rejected.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
guid | string | — | Idempotency key. If the same guid arrives twice, the duplicate is silently dropped. |
locationId | int? | ◻︎ | See routing above. |
locationShortCode | string | ◻︎ | See routing above. |
spotId | int? | — | ID of the target spot (table, room, pickup/delivery). |
spotNumber | int? | — | Spot number, when ID is unknown. |
userInfo | UserInfo | ✅ | Who placed the order. email is required. |
deliveryInfo | DeliveryInfo | — | Delivery address. Required for home delivery. |
takeaway | bool | ✅ | true for takeaway, false for dine-in. |
note | string | — | Free-form note from the guest (allergens, special requests). |
qrCode | string | — | See routing. |
entries | Entry[] | ✅ | Ordered items. |
preOrderTime | long? | — | Pre-order slot, Unix time in milliseconds UTC. |
shortCode | string | — | Pickup / delivery reference (e.g. zw1356). |
tip | decimal? | — | Tip amount. |
isPaid | bool | — | true if the order has already been paid externally. |
grandTotal | decimal? | ✅ | Total of all entries + tip. Used to validate against server-side pricing. |
Entry
| Field | Type | Required | Description |
|---|---|---|---|
productNr | string | ✅ | Product number in APRO. |
name | string | — | Display name — informational only; APRO trusts productNr. |
preOrderTime | long? | — | Per-item pre-order slot. |
quantity | double | ✅ | Quantity ordered. |
price | double? | — | Override the system price for this line (discounts, campaigns). |
note | string | — | Item-level note (e.g. Ohne Zwiebeln). |
addons | Addon[] | — | Add-on selections. |
Addon
| Field | Type | Required | Description |
|---|---|---|---|
productNr | string | ✅ | Product number of the add-on. |
name | string | — | Display name. |
quantity | double | ✅ | Quantity. |
price | double? | — | Override the system price. |
UserInfo
| Field | Type | Required | Description |
|---|---|---|---|
firstName | string | — | |
lastName | string | — | |
email | string | ✅ | Contact email for receipts and status updates. |
phone | string | — | |
locale | string | — | IETF locale, e.g. de-DE. |
nickname | string | — | Short name shown at pickup. |
DeliveryInfo
| Field | Type | Description |
|---|---|---|
name | string | Recipient label. |
companyName | string | |
city | string | |
zip | string | |
street | string | |
country | string | |
floor | string | |
stairway | string | |
door | string | |
note | string | Delivery instructions. |
Examples
Minimal order
{ "locationShortCode": "vienna-main", "takeaway": true, "userInfo": { "email": "guest@example.com" }, "entries": [{ "productNr": "123", "quantity": 1 }], "grandTotal": 9.99}Download: external-order-minimal.json
Full order with delivery and add-ons
{ "guid": "123e4567-e89b-12d3-a456-426614174000", "locationId": 101, "spotId": 15, "spotNumber": 10, "shortCode": "zw1356", "userInfo": { "firstName": "Max", "lastName": "Mustermann", "email": "max.mustermann@example.com", "phone": "+491234567890", "locale": "de-DE", "nickname": "Max" }, "takeaway": false, "note": "Bitte schnell liefern", "qrCode": "QR1234567890", "deliveryInfo": { "name": "Max Mustermann", "city": "Wien", "zip": "1010", "street": "Stephansplatz 1", "country": "AT", "floor": "3", "stairway": "A", "door": "12" }, "entries": [ { "productNr": "123", "name": "Wiener Schnitzel", "quantity": 2, "price": 9.99, "note": "Extra scharf", "addons": [ { "productNr": "501", "name": "Pommes", "quantity": 2, "price": 3.5 } ] }, { "productNr": "31231", "name": "Burger Classic", "quantity": 1, "note": "Ohne Zwiebeln" } ], "preOrderTime": 1723574400000, "tip": 1.2, "isPaid": true, "grandTotal": 28.18}Download: external-order-full.json
Idempotency
Always set guid to a stable, client-generated UUID. APRO uses it to
deduplicate retries — if a response is lost in transit and you retry, the
second POST is a no-op and returns success.
Pricing
APRO re-prices every line server-side from productNr. price on an
entry or add-on only takes effect when explicitly passed; grandTotal is
checked against the server total and an inconsistent payload is rejected.
Use it both as a safety net and as a mechanism to pass through
campaign-specific discounts.