Skip to content

Sandbox merchants

A sandbox merchant is a real LithosPOS company created by the same provisioning pipeline as a paying customer, flagged as demo data and owned by your organization. It has its own database, its own back office and its own ids. You can write to it freely.

From Sandbox → Provision merchant, give it a label and a country. The dialog then asks Add sample data for testing? Tick the kinds of data you want — categories, brands, items, modifiers, menus, recipes, customers, online orders, sales & reports, and purchases & stock — or untick the option for an empty merchant. LithosPOS creates the company, adds the sample data you picked as real rows, and returns credentials once:

Shown once
companyId 104271
label Coffee chain — QA
ownerEmail you+acme-sb1@example.com
ownerPassword 7Kq2Xd9MvR3nT4wB

The owner email is a plus-addressed alias of your own developer email, so verification and password-reset mail reaches your inbox. Sign in to the merchant back office with those credentials to see the effect of your API calls in the product itself.

Each organization can hold three active sandbox merchants. A fourth returns developer.sandbox_limit; deactivate one you no longer need first.

Sandbox access needs no approval. When you provision a merchant, LithosPOS creates a sandbox grant for every app in the organization, and when you create a new app it is granted against every existing sandbox merchant. That is why merchant_id is optional at mint time when the organization has exactly one sandbox merchant.

Deactivating a sandbox merchant revokes its grants. Existing tokens keep working until they expire — up to 900 seconds — and then stop.

Environment consistency is enforced in both directions and cannot be overridden:

  • A sandbox credential (lp_app_sb…) may only reach companies flagged as demo data.
  • A production credential (lp_app_pk…) may only reach companies that are not.

Violations fail at mint time with developer.env_mismatch. This is what stops a half-configured test harness from writing into a live restaurant.

Sandbox merchants are provisioned from the same baseline as new customers, so they arrive with a standard starting configuration rather than an empty database — a store, a terminal, payment types, units and an exempt tax. Whatever else is there is what you ticked at provisioning time:

  • Sample data you ticked is created as real rows at provisioning time, so every list and report returns data from the first pull — no POS pairing needed. The rows are ordinary merchant data: you can read, edit and delete them like anything you create yourself.
    • Sales & reports seeds two bills a day for the trailing week, plus variety bills that between them cover the order types (dine-in, takeaway, home delivery, aggregator), card and wallet payment types, tips, a service and a delivery charge, bill discounts, a waiter and a delivery rider, and one refund — so the pay-types, order-types, charges, discounts, tips, employee, refund and daily-sales reports all have rows from day one.
    • Purchases & stock seeds a supplier with a received purchase, income and expense entries, cash in and out, a stock write-off and a transfer to a second demo store — the purchase, adjustment, transfer reports and the business summary’s non-sales legs all read these.
    • Recipes seeds its demo recipe plus a production run consuming the ingredients.
    • Dependencies come along automatically: ticking Sales & reports also seeds the items it sells and the customers on its bills, and the items bring their brands and categories.
  • An empty merchant (option unticked) has only the baseline configuration. Build the rest of the fixture — categories, brands, taxes, items, menus, customers — through the API, which doubles as an integration test of your own write paths.

Anything you did not tick, and have not created yourself, is simply empty. A list call returns "data": [] with "total": 0, and fetching a single record by an id that does not exist returns 404. The API never substitutes placeholder rows, so what you read in sandbox is always what is stored.

To discover what the baseline already holds, read it before you assume ids:

Terminal window
curl -s "$API_BASE_URL/stores" -H "Authorization: Bearer $ACCESS_TOKEN"
curl -s "$API_BASE_URL/taxes" -H "Authorization: Bearer $ACCESS_TOKEN"
curl -s "$API_BASE_URL/categories" -H "Authorization: Bearer $ACCESS_TOKEN"

Sandbox is not limited to the client-credentials quickstart. The full merchant consent flow runs against sandbox tenants, at the same URL a live merchant uses, so you can build and demo your Connect LithosPOS experience before review.

Three things make it work:

  • Your sandbox client id. lp_app_sb… is accepted at https://my.lithospos.com/oauth/authorize whatever state the app’s review is in. It will only consent against sandbox tenants belonging to your own organization.
  • The sandbox owner login. The consent screen is a merchant surface, so sign in with the ownerEmail / ownerPassword that provisioning gave you — not your developer console account. Only the account owner can approve.
  • Loopback redirect URIs. http://localhost:3000/callback and http://127.0.0.1[:port] are accepted alongside https:// URIs, so the redirect can land on your dev server. Add them to the app’s redirect URI list first; matching is exact.
https://my.lithospos.com/oauth/authorize
?response_type=code
&client_id=lp_app_sbK2m9Qx7Rt4
&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback
&state=e3b0c44298fc1c149afbf4c8996fb924

Refresh rotation, the 60-second grace window, reuse detection and revocation all behave exactly as they do in production — sandbox refresh tokens are simply lp_rt_sb_…. Test the family-revocation path here, where losing a connection costs nothing.

ADSR apps have nothing to set up: sandbox tenants are auto-granted, so a lp_ak_sb_… API key reads them immediately.

AreaBehaviour
PaymentsNo card processing. Sales carry payment types but no acquirer is involved
HardwareNo terminals, printers or KDS screens are attached unless you pair them yourself
LoadSandbox clusters are sized for development. Do not use them for load testing
LongevityDemo data may be reset during platform maintenance. Never treat it as durable storage
Merchant identitySandbox company ids are not related to any live merchant id

Sandbox and production credentials are separate objects — you do not “promote” a sandbox key. When your app is approved, LithosPOS issues a production credential, and live merchants authorize it themselves: through consent for Full API, Online Order API, Reservation API and Table QR Payment apps, through an access request for ADSR. Your code should read the client id, the secret and the redirect URI from configuration so the only change is an environment variable.

Read the go-live checklist for what review expects to see.