Xpand Integrator Callback APIs (1.0)

Overview

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.

Review Shopping Cart

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.

Diagram

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.

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Response samples

Content type
application/json
{
  • "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
}

Age Verification

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.

Diagram

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.

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Scan Promo Code

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.

Diagram

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.

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Check Promo Code

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.

Diagram

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.

Request Body schema: application/json
required
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.

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Response samples

Content type
application/json
Example
{
  • "valid": true,
  • "message": { },
  • "promoCode": "508a781fead1"
}

Pre-authorize Payment

The payment processing callback APIs provide two hook points into the Xpand Autonomous Store order flow:

  • When the user initially submits the order a pre-auth for order amount is processed
  • When the user picks up the order the payment is finalized with the actual final amount

The payment pre-auth sequence on order placement is:

Diagram

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.

Request Body schema: application/json
required
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 POST /shopping-cart callback API call.

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

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Finalize Payment

The payment processing callback APIs provide two hook points into the Xpand Autonomous Store order flow:

  • When the user initially submits the order a pre-auth for order amount is processed
  • When the user picks up the order the payment is finalized with the actual final amount

The payment finalize sequence on order pickup is:

Diagram

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.

Request Body schema: application/json
required
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

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Process Refunds

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:

  • Order finished processing (status=delivered) with 2/3 items (-$1.99).
  • Webhook sent with status delivered and 2/3 in fulfilledQuantity property.
  • Customer complains about another defective item. Operator updates (1/3 items, -$3.98).
  • Process Update Now endpoint triggered.
  • Webhook sent with status delivered and 1/3 in fulfilledQuantity property.
  • Process Update Now endpoint triggered again (operator clicked button again).

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).

Request Body schema: application/json
required
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

Responses

Request samples

Content type
application/json
{
  • "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"
    }
}

Print Invoice

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.

Request Body schema: application/json
required
digitalShelfId
required
integer (DigitalShelfId)

ID of the Xpand Digital Shelf station the user is placing the order from

Responses

Request samples

Content type
application/json
{
  • "digitalShelfId": 6
}