Used Newie, our AI search tool in the docs? Take a 2-minute survey to rate your experience!

Running a self-checkout integration locally

Prev Next

Before running the self-checkout module live in your stores, you can also try out the self-checkout integration locally before obtaining actual platform credentials.

NewStore provides a set of local stub servers that mirror the real platform APIs. They serve the same request and response shapes as the live platform but require no authentication. No credentials or network access is required too. This allows you to validate the self-checkout flow before you connect to a real environment.

Prerequisites

  • Ensure that you have access to the stub server package from NewStore. The stub servers are bundled with the self-checkout plugin under plugin/skills/self-checkout-guidance/scripts/stubs/. If you need the package or its latest version, talk to your point of contact at NewStore.

  • Ensure that ports 4501–4505 are free on your machine to allow these stub servers to run.

Running the stub servers

Stub server

Port

API

Catalog stub

http://localhost:4501

GET /catalogs/{catalogId}/products — barcode to product and price

Tax/Totals stub

http://localhost:4502

POST /taxes/standard-quotations — cart totals and tax calculation

Order stub

http://localhost:4503

POST /orders — order placement

Receipt stub

http://localhost:4504

POST /receipts — create the receipt document

Promotions stub

http://localhost:4505

POST /promotions/calculations — automatic promotions and coupon codes

All five stubs accept requests without an Authorization header. No token acquisition is needed during local development.

The stub servers are plain HTTP and listen on all interfaces, Node.js is needed only to run them, an iOS simulator reaches them on the host's localhost, an Android emulator uses 10.0.2.2, a physical device needs the host's LAN address, and native platforms may block plain HTTP by default, so allow it for these development hosts only.

Starting the stub servers

bash scripts/stubs/start-stubs.sh

This starts all five stub servers in the background. Confirm they are running by sending a request to one of the stub paths directly:

GET http://localhost:4501/catalogs/storefront-catalog-en/products?id=0123456789012&id_type=ean13&pricebook=default
Accept-Language: en-US

A successful response returns a products array containing one product, in this case Organic Bananas.

Using demo products for self-checkout

The catalog stub recognizes three EAN-13 barcodes.

EAN-13

Product

Price (price.amount)

tax_class

0123456789012

Organic Bananas

129 ($1.29)

grocery-exempt

0987654321098

Sparkling Water 12pk

599 ($5.99)

standard

1111111111111

Whole Milk 1gal

349 ($3.49)

grocery-exempt

To test the not-found path, use any other EAN-13 value, for example 9999999999999. The stub returns an empty products array. Ensure that your catalog adapter treats both products: null and products: [] as not found.

Using demo promotions

The promotions stub applies one automatic promotion and recognizes three coupon codes. The coupon WELCOME10 is the one used in Tutorial: Setting up self-checkout in a store, so the coupon flow of the tutorial also works against the stubs. The stub applies it per unit with scope: ITEM, while the whole-cart coupon of the tutorial comes back from the platform with scope: ORDER.

Trigger

Effect

Every Sparkling Water 12pk unit

FIXED 100 off, automatically (promo-water-100)

Coupon WELCOME10

PERCENTAGE 10% off every eligible unit

Coupon FIVEOFF

FIXED 500 off the cart, scope: ORDER, prorated over the units

Coupon EXPIRED

messages entry discount_code_expired

Any other code

messages entry discount_code_invalid

A unit sent with a list_price different from its price comes back manual_discount_forbidden: true with no discounts, as on the platform.

Handling cross-origin requests

Browsers block requests to a different origin than the page, based on the browser's CORS policy. When your frontend runs on localhost:3000 and the stub servers run on localhost:4501–4505, the browser blocks every fetch to the stubs unless you handle this. This applies only to browser-based apps, because native and desktop apps call the stubs directly.

Select the approach that fits your tooling stack.

  • Bundler proxy — Most bundlers such as Vite, webpack, or Next.js have a built-in proxy config that forwards requests server-side, making them same-origin as the browser. Check your bundler's documentation. This is the recommended approach.

  • Service worker — Intercept fetch calls in the browser and rewrite the URL.

  • Reverse proxy — Route all traffic through a single origin using nginx, Caddy, or similar web servers.

The right choice depends on your stack.

Environment variables

Configure your application with environment variables so that switching from the stub servers to the real platform requires no code changes.

Variable

Stub value

Real platform value

CATALOG_URL

http://localhost:4501

https://{your-tenant}.{env}.newstore.net

TAX_URL

http://localhost:4502

https://{your-tenant}.{env}.newstore.net

ORDER_URL

http://localhost:4503

https://{your-tenant}.{env}.newstore.net

RECEIPT_URL

http://localhost:4504

https://{your-tenant}.{env}.newstore.net

PROMOTIONS_URL

http://localhost:4505

https://{your-tenant}.{env}.newstore.net

STORE_ID

store-01

Your store's ID on the platform

STORE_TIMEZONE

America/New_York

Your store's IANA time zone

STORE_ADDRESS_LINE_1

121 Spring Street

Your store's street address

STORE_CITY

New York

Your store's city

STORE_STATE

NY

Your store's state/region

STORE_ZIP

10012

Your store's postal code

STORE_COUNTRY

US

Your store's country code (ISO 3166-1 alpha-2)

Use a real store address even locally. The tax stub validates that address_line_1, city, zip_code and country_code are present and rejects a placeholder with 422, the same way the real platform does — so an address that only looks plausible fails during development rather than after you switch environments. On the real platform the tax provider resolves the tax jurisdiction from this address, so it must be the store's actual one.

The promotions request requires store.id and store.timezone, and the receipt requires the store ID, label, and time zone, so set STORE_ID and STORE_TIMEZONE even when you build against the stubs.

Switching to the real platform

When you have provisioned credentials, switching involves two changes:

  1. Update the base URLs — replace the localhost values with your tenant and environment.

  2. Add the Authorization header — include Authorization: Bearer {access_token} on all requests, and using the client ID of the Application client you created in Omnichannel Manager. See Authentication and setup for self-checkout for the full authorization flow.

No other code changes are required. The request and response shapes are identical between the stubs and the real platform.

Next steps

  • Scan a demo product end to end, including catalog lookup, promotions calculation, tax quotation, order placement, and receipt generation.

  • When your self-checkout flow works via all five stubs, request platform credentials from NewStore to deploy self-checkout integration in your live environment.