This API spec details the callback APIs that an integrator of the Xpand Autonomous Store should implement.
These callback APIs represent hook points in the Xpand Autonomous Store flow where control of a certain part of the flow is handled by the integrator by design. This allows the integrator to implement any desired business logic without requiring a specific implementation on the Xpand Autonomous Store side.
The sections below include explanations and sequence diagrams in the beginning of each section to elaborate and clarify the specific flow in which the callback API is required, and what its effect on the overall flow is.
With the exception of the POST /shopping-cart API call, the API calls listed in this spec represent
triggers for potentially long human-interaction flows. As a result these calls are non-blocking and
expected to return immediately while the responses carry no result information.
The actual final result of these flows should then be sent back to the Xpand Autonomous Store using a matching endpoint. Note that these endpoints are deliberately identical on both sides, i.e:
# Integrator callback API
POST /payments/preauth ---> begin payment pre-auth flow
# Xpand Autonomous Store Management API
POST /payments/preauth <--- submit payment pre-auth flow result
To easily correlate between these matching API call pairs, each Integrator callback API includes some unique identifier that is required to be included when making the result API call. This identifier differs in each API call pair and is mentioned in the description of the individual API endpoints.
Some of the API calls listed in this spec carry an additional digitalShelfId property that uniquely
identifies the Xpand Autonomous Store Digital Shelf station that the user is interacting with. This in
turn should allow the integrator to make any correlation necessary to the exact lobby equipment paired
with this specific Digital Shelf station, such as POS unit, printer, tablet, or other interactive equipment.
The Review Shopping Cart callback API is called when a user enters the "review order" stage of placing an order. This is before payment processing starts. The user is presented with the final price for each product and the order total price. The call therefore can apply any desired discounts, promotions, campaigns, loyalty programs and so on, as well as calculate tax and deposit.

The request will contain the products that the user has selected, and the response should indicate the final price for each product, modifiers applied, and grad total of the order.
The request can contain an optional promoCode obtained from a previous promo code scan or check flows.
If provided, the integrator can include the promo code into the shopping cart calculation.
| siteId required | integer (SiteId) Site ID of the site the user is in |
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
| promoCode | string Optional promo code obtained previously by scanning or manual entry |
required | Array of objects (ShoppingCartProducts) non-empty The list of products that the user selected for the order |
required | object (User) Information about the user placing the order. All information about the user is optional and should be assumed to be potentially unavailable. |
{- "siteId": 17,
- "digitalShelfId": 6,
- "promoCode": "508a781fead1",
- "products": [
- {
- "productId": 1234,
- "productExternalId": "J57S",
- "quantity": 2,
- "modifiers": {
- "strength": "strong",
- "milk": "with milk"
}
}, - {
- "productId": 5678,
- "productExternalId": null,
- "quantity": 1
}
], - "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}
}{- "invoiceLines": [
- {
- "productId": 1234,
- "amount": 4.99,
- "sublines": [
- {
- "description": "Sales Tax",
- "amount": 0.4
}
]
}, - {
- "productId": 5678,
- "amount": 12.99,
- "sublines": [
- {
- "description": "Sales Tax",
- "amount": 1.04
}, - {
- "description": "Member Discount",
- "amount": -2
}
]
}, - {
- "description": "Delivery Fee",
- "amount": 2.99,
- "sublines": [
- {
- "description": "Sales Tax",
- "amount": 0.24
}
]
}
], - "total": 22.36,
- "ageVerificationRequired": true
}The Age Verification callback API is called during the review order stage before the payment flow, but after the calculate shopping cart point. If the user chooses to continue with placing the order, the Xpand Autonomous Store UI will prompt them for age verification, if the order contains products that are age restricted.

This API call only starts the age verification flow, it is not expected that the call will block until the user completes the age verification flow. Therefore the response body does not carry the age verification result and there is no requirement for the response other than a 2xx HTTP status code.
The result of the age verification flow should be submitted to the Xpand Autonomous Store API through
the POST /age-verification endpoint (see the Xpand Autonomous Store Management API spec for details).
To easily correlate between potentially concurrent flows, the integrator must store the ageVerificationId
from this request and use it in the result POST /age-verification API call.
| ageVerificationId required | integer Unique ID for this age verification flow. This ID should be used in the age verification result API call for correlation. |
| siteId required | integer (SiteId) Site ID of the site the user is in |
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
required | Array of objects (ShoppingCartProducts) non-empty The list of products that the user selected for the order |
required | object (User) Information about the user placing the order. All information about the user is optional and should be assumed to be potentially unavailable. |
{- "ageVerificationId": 10476,
- "siteId": 17,
- "digitalShelfId": 6,
- "products": [
- {
- "productId": 1234,
- "productExternalId": "J57S",
- "quantity": 2,
- "modifiers": {
- "strength": "strong",
- "milk": "with milk"
}
}, - {
- "productId": 5678,
- "productExternalId": null,
- "quantity": 1
}
], - "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}
}The Scan Promo Code callback API is optionally called during the review order stage before the age verification and payment flows, after an initial call to review shopping cart. If the user chooses to scan a promo code the Xpand Autonomous Store UI will indicate to the user to follow the instructions on the customer terminal and then wait for the scan result. If the result is successful, the Xpand Autonomous Store UI will repeat the Review Shopping Cart API call with the new promo code to update the shopping cart line items.

This API call only starts the scan promo code flow, it is not expected that the call will block until the user completes the scan promo code flow. Therefore the response body does not carry the scan promo code result and there is no requirement for the response other than a 2xx HTTP status code.
The result of the scan promo code flow should be submitted to the Xpand Autonomous Store API through
the POST /promo-code/scan endpoint (see the Xpand Autonomous Store Management API spec for
details). To easily correlate between potentially concurrent flows, the integrator must store the
promoCodeScanId from this request and use it in the result POST /promo-code/scan API call.
| promoCodeScanId required | integer Unique ID for this scan promo code flow. This ID should be used in the scan promo code result API call for correlation. |
| siteId required | integer (SiteId) Site ID of the site the user is in |
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
required | object (User) Information about the user placing the order. All information about the user is optional and should be assumed to be potentially unavailable. |
{- "promoCodeScanId": 10476,
- "siteId": 17,
- "digitalShelfId": 6,
- "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}
}The Check Promo Code callback API is optionally called during the review order stage before the age verification and payment flows, after an initial call to review shopping cart. If the user chooses to manually enter a promo code the Xpand Autonomous Store API will perform this API call to verify the promo code in real-time. If the result is successful, the Xpand Autonomous Store UI will repeat the Review Shopping Cart API call with the new promo code to update the shopping cart line items.

Note that the response contains a promoCode property which is the actual promo code string that should be
used in the Review Shopping Cart API call. This actual code may or may not be identical to the original code
entered by the user. This can be used for example by the client or integrator to implement a mechanism of
distributing generic codes which can be used multiple times (e.g. "Fall2025"), but then map them to one-time
codes for tracking purposes in individual orders.
| promoCode required | string The promo code as entered by the user |
| siteId required | integer (SiteId) Site ID of the site the user is in |
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
required | object (User) Information about the user placing the order. All information about the user is optional and should be assumed to be potentially unavailable. |
{- "promoCode": "Fall2025",
- "siteId": 17,
- "digitalShelfId": 6,
- "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}
}{- "valid": true,
- "message": { },
- "promoCode": "508a781fead1"
}The payment processing callback APIs provide two hook points into the Xpand Autonomous Store order flow:
The payment pre-auth sequence on order placement is:

The full order details are passed, as well as the amount previously calculated and returned by the
POST /shopping-cart callback API call for this order and displayed to the user. Note that the Xpand
Autonomous Store does not assume or dictate the actual amount to debit the user for. This property
is included only for information purposes. The actual amount to be used is up to the integrator.
This API call only starts the payment pre-auth flow, it is not expected that the call will block until the user completes the payment pre-auth flow. Therefore the response body does not carry the payment pre-auth result and there is no requirement for the response other than a 2xx HTTP status code.
The result of the payment pre-auth flow should be submitted to the Xpand Autonomous Store API through
the POST /payments/preauth endpoint (see the Xpand Autonomous Store Management API spec for details).
To easily correlate between potentially concurrent flows, the integrator must store the paymentId from
this request and use it in the result POST /payments/preauth API call.
| paymentId required | integer (PaymentId) Unique ID of this payment flow |
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
| amount required | number <float> The amount previously calculated and returned by the Note that the Xpand Autonomous Store does not assume or dictate the actual amount to debit the user for. This property is included only for information purposes. The actual amount to be used is up to the integrator. |
required | object (Order) Complete order information for payment purposes |
{- "paymentId": 11938,
- "digitalShelfId": 6,
- "amount": 18.42,
- "order": {
- "id": 8642,
- "siteId": 17,
- "systemId": 42,
- "displayCode": 7465,
- "status": "payment",
- "products": [
- {
- "productId": 1234,
- "productExternalId": "J57S",
- "quantity": 2,
- "fulfilledQuantity": 0,
- "modifiers": {
- "strength": "strong",
- "milk": "with milk"
}
}, - {
- "productId": 5678,
- "productExternalId": null,
- "quantity": 1,
- "fulfilledQuantity": 0,
- "integratedProductStatus": "pending",
- "modifiers": {
- "size": "large"
}
}
], - "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}, - "deliveryDate": "2023-06-15",
- "deliveryTime": "14:30",
- "createdAt": "2023-06-14T10:30:00Z",
- "updatedAt": "2023-06-14T15:45:00Z"
}
}The payment processing callback APIs provide two hook points into the Xpand Autonomous Store order flow:
The payment finalize sequence on order pickup is:

The full order details are passed, as well as the transactionId previously sent by the
POST /payments/preauth endpoint for this order (see the Xpand Autonomous Store Management API
spec for details). Note that the Xpand Autonomous Store does not calculate or assume the final amount
to debit the user for. It is up to the integrator to calculate this final amount based on the final state
of the order which is included in this API call.
This API call only starts the payment finalization flow, it is not expected that the call will block until the user completes the payment finalization flow. Therefore the response body does not carry the payment finalization result and there is no requirement for the response other than a 2xx HTTP status code.
The result of the payment finalization flow should be submitted to the Xpand Autonomous Store API through
the POST /payments/finalize endpoint (see the Xpand Autonomous Store Management API spec for details).
To easily correlate between potentially concurrent flows, the integrator must store the paymentId from
this request and use it in the result POST /payments/finalize API call.
| paymentId required | integer (PaymentId) Unique ID of this payment flow |
| transactionId | string Transaction ID from the pre-authorization result call (if provided) |
required | object (Order) Complete order information for payment purposes |
{- "paymentId": 11938,
- "transactionId": "txn_preauth_456789",
- "order": {
- "id": 8642,
- "siteId": 17,
- "systemId": 42,
- "displayCode": 7465,
- "status": "payment",
- "products": [
- {
- "productId": 1234,
- "productExternalId": "J57S",
- "quantity": 2,
- "fulfilledQuantity": 0,
- "modifiers": {
- "strength": "strong",
- "milk": "with milk"
}
}, - {
- "productId": 5678,
- "productExternalId": null,
- "quantity": 1,
- "fulfilledQuantity": 0,
- "integratedProductStatus": "pending",
- "modifiers": {
- "size": "large"
}
}
], - "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}, - "deliveryDate": "2023-06-15",
- "deliveryTime": "14:30",
- "createdAt": "2023-06-14T10:30:00Z",
- "updatedAt": "2023-06-14T15:45:00Z"
}
}The Process Refunds Now endpoint is used to trigger an immediate calculation and processing of any refunds owed to the customer based on cancelled products in their order (latest state).
Refunds should be automatically processed based on webhook calls if the order was only partially fulfilled. However since it is recommended to employ a small timeout between last webhook call and the processing to allow consumptions of multiple updates / events - the need arises for a way to trigger the process immediately in case the operator is currently dealing with a customer.
Ultimately the refund process should be idempotent and it shouldn't matter how many times and through what channel it was triggered (process now endpoint or webhooks). This endpoint is present for convenience purposes when dealing with customers.
The request payload contains a full current snapshot of the order to allow the easy immediate processing. Care should be taken on the integrator side to implement the process in an idempotent manner. For example the following is a valid series of events that should yield a deterministic outcome:
delivered) with 2/3 items (-$1.99).delivered and 2/3 in fulfilledQuantity property.delivered and 1/3 in fulfilledQuantity property.The endpoint is not expected to yield any immediate result and any 2xx response with an empty or non-empty body will be accepted as a valid response (the body will be ignored). The endpoint is only meant to trigger a background refund process and the request does not need to block until it finishes (although it is possible to implement it this way if desired).
| paymentId required | integer Unique ID of the original payment flow associated with the order |
| transactionId | string Transaction ID from the pre-authorization result call (if one was provided) |
required | object (Order) Complete order information for payment purposes |
{- "paymentId": 11938,
- "transactionId": "txn_preauth_456789",
- "order": {
- "id": 8642,
- "siteId": 17,
- "systemId": 42,
- "displayCode": 7465,
- "status": "payment",
- "products": [
- {
- "productId": 1234,
- "productExternalId": "J57S",
- "quantity": 2,
- "fulfilledQuantity": 0,
- "modifiers": {
- "strength": "strong",
- "milk": "with milk"
}
}, - {
- "productId": 5678,
- "productExternalId": null,
- "quantity": 1,
- "fulfilledQuantity": 0,
- "integratedProductStatus": "pending",
- "modifiers": {
- "size": "large"
}
}
], - "user": {
- "name": "John Doe",
- "address": "123 Main St, Anytown, AT 12345",
- "phoneNumber": "+1-555-123-4567",
- "locale": "en-US"
}, - "deliveryDate": "2023-06-15",
- "deliveryTime": "14:30",
- "createdAt": "2023-06-14T10:30:00Z",
- "updatedAt": "2023-06-14T15:45:00Z"
}
}The print invoice callback API is called when a user asks to print an invoice for their order at the Digital Shelf. This allows customers to get a physical receipt or invoice after their order has been completed.
This API call only starts the invoice printing flow, it is not expected that the call will block until the invoice printing is completed. Therefore the response body does not carry the printing result and there is no requirement for the response other than a 2xx HTTP status code.
The result of the invoice printing flow should be submitted to the Xpand Autonomous Store API through
the POST /print-invoice endpoint (see the Xpand Autonomous Store Management API spec for details).
Unlike other integration endpoint pairs, the correlation between API calls for this endpoint is done
solely based on the digitalShelfId parameter.
| digitalShelfId required | integer (DigitalShelfId) ID of the Xpand Digital Shelf station the user is placing the order from |
{- "digitalShelfId": 6
}