Sandbox stores
What a sandbox store contains, how to reset it, and its limits.
On this page
A sandbox store is a real Dukkan store in every respect except that it is born with synthetic data and flagged as a development store. You test apps against it and push themes to it without ever touching a merchant. This page explains what it ships with, how you manage it, and where its limits are.
What a sandbox contains#
Every sandbox is seeded with the full matrix a carrier, notifier or accounting app needs, so you never build data by hand:
| Area | Contents |
|---|---|
| Catalog | 12 products with variants covering every variant status (active, out_of_stock, hidden, discontinued) plus one product without inventory tracking. |
| Inventory | Two locations (the default and a warehouse), an initial movement per variant per location, then one movement of every other reason. |
| Discounts | One of every value_type: a percentage code (RAMADAN10), an automatic fixed amount, free shipping (FREESHIP), and buy X get Y (inactive). |
| Orders | One order in every state: placed, approved, processing (with a partial pending fulfillment), shipped, delivered, delivered_failed, returned (unpaid, no refund), partially_refunded (refund with a line breakdown), cancelled, and a POS completed order with net lines (line_pricing: net). |
| Payments | Delivered orders are paid through a cod_collection row in the payments ledger, never a toggle. |
| Currencies | A USD order with a scale-8 exchange-rate snapshot (exchange_rate.scale: 8). |
All amounts are integer minor units; Syrian pounds have no decimals, US dollars have two. See Money in minor units.
Create a sandbox#
From Sandbox stores choose New sandbox and name it (optional, up to 80 characters). The store is created and seeded in the background by the merchant runtime; its status moves from provisioning to active within moments. The limit is 3 live sandboxes per organization (provisioning, active, resetting and pending requests all count).
Reset, renew, purge#
Sandboxes are managed through ordered commands executed by the merchant runtime; one open command per store at a time:
| Command | Effect |
|---|---|
Reset (reset) |
Wipes everything, including data your app created, then reseeds from scratch. |
Renew (renew) |
Extends the expiry by 90 days from the current expiry or from today, whichever is later. |
Purge (purge) |
Deletes the store permanently and frees its quota slot. |
A sandbox lives 90 days and then becomes expired; CLI tokens bound to it stop working until you renew it. None of these commands ever applies to a real store linked for testing.
Warning
A reset is refused while a live payout covers any of the sandbox's revenue ledger entries. Cancel the payout first, then reset.
One theme per sandbox#
The server derives an external theme's identity from the sandbox the CLI token belongs to (sandbox-<id>), so two themes can never share one sandbox: pushing theme A with theme B's token appends a version to B. Create one sandbox per theme.
Trigger your first event#
Open the sandbox storefront at https://dukkan.one/stores/YOUR_SANDBOX_SLUG, add a product to the cart and check out with cash on delivery. That emits order.created immediately, then order.status_changed for every transition you make from the merchant admin or through PATCH /orders/{id}/status. Confirm the cash collection in the merchant admin to watch order.paid come from the ledger rather than from delivery.
Linked stores#
You can also link a real store your organization owns to test app installs. A linked store is never seeded, never reset and never accepts theme pushes; it exists for development distribution only.
Limits#
| Limit | Value |
|---|---|
| Live sandboxes per organization | 3 |
| Sandbox lifetime | 90 days, renewable |
| Concurrent commands per store | 1 |
| Theme API requests per CLI token | 120 per minute |
| CLI tokens | 1-hour access, 30-day refresh, rotated on every use |