{
  "info": {
    "name": "Scanimart Connect",
    "description": "Every endpoint of the Scanimart Connect API (version 2026-10-01), in the order an integration meets them.\n\nSet `api_key` to a test key (`sk_test_…`) and run the collection against the sandbox: it places, accepts, packs and delivers a test order, syncs stock, books the sale and exercises webhook endpoints, checking each answer and carrying ids forward.\n\nGenerated from openapi/connect.json by postman/build.mjs — edit that, not this file. Docs: https://developers.scanimart.com",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "4b0f3a8e-5c7d-4e2a-9f61-0c5a7e2b1d93"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://sandbox.api.scanimart.com"
    },
    {
      "key": "api_key",
      "value": ""
    },
    {
      "key": "webhook_url",
      "value": "https://example.com/scanimart/webhooks"
    },
    {
      "key": "run_destructive",
      "value": "0"
    },
    {
      "key": "store_id",
      "value": ""
    },
    {
      "key": "company_id",
      "value": ""
    },
    {
      "key": "order_id",
      "value": ""
    },
    {
      "key": "second_order_id",
      "value": ""
    },
    {
      "key": "accept_key",
      "value": ""
    },
    {
      "key": "now",
      "value": ""
    },
    {
      "key": "run_id",
      "value": ""
    },
    {
      "key": "event_id",
      "value": ""
    },
    {
      "key": "endpoint_id",
      "value": ""
    },
    {
      "key": "delivery_id",
      "value": ""
    }
  ],
  "item": [
    {
      "name": "1. Account",
      "item": [
        {
          "name": "Check your key",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"company\",\"key\",\"mode\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.company?.id !== undefined) pm.collectionVariables.set('company_id', body?.company?.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/ping",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ping"
              ]
            },
            "description": "`ping` — Returns the company and key you are authenticated as. The first call to make."
          },
          "response": []
        }
      ]
    },
    {
      "name": "2. Stores",
      "item": [
        {
          "name": "List connected stores",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.data?.[0]?.id !== undefined) pm.collectionVariables.set('store_id', body?.data?.[0]?.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores"
              ]
            },
            "description": "`listStores` — Only stores with an active connection to the POS company authenticated by your API key, in that key's live or test mode. A store-scoped key returns only its own connected store. Unconnected stores, revoked connections and other POS companies' stores are never listed."
          },
          "response": []
        },
        {
          "name": "Get a connected store",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"active\",\"address\",\"area\",\"city\",\"gstin\",\"id\",\"latitude\",\"longitude\",\"name\",\"services\",\"status\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}"
              ]
            },
            "description": "`getStore` —"
          },
          "response": []
        },
        {
          "name": "Connect a store with its one-time code (an expired code is refused)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 400', () => pm.expect(pm.response.code).to.be.oneOf([400]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('error code is invalid_connection_code', () => pm.expect(body.error && body.error.code).to.eql('invalid_connection_code'));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"code\": \"XXXX-XXXX\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/connections/claim",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "claim"
              ]
            },
            "description": "`claimConnection` — The store owner generates a code in the Scanimart retailer app (Settings → POS software → Connect your POS) and enters it in your POS. Exchange it here for access to that store. Codes expire after 15 minutes and work once. Claiming a store you are already connected to returns the existing link. Needs a company-wide key: the store joins your whole company.\n\nIn live, `code` is what the store owner generated in the Scanimart retailer app. A made-up code is refused, which is what this request checks."
          },
          "response": []
        }
      ]
    },
    {
      "name": "3. Sandbox: place orders",
      "item": [
        {
          "name": "Simulate a paid online order",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 201', () => pm.expect(pm.response.code).to.be.oneOf([201]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.order_id !== undefined) pm.collectionVariables.set('order_id', body?.order_id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"lines\": [\n    {\n      \"barcode\": \"8901030865278\",\n      \"quantity\": 2\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/orders",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "orders"
              ]
            },
            "description": "`simulateOrder` — Creates a paid delivery order at your test store and sends `order.placed`. Requires a company-wide test key. Sandbox only."
          },
          "response": []
        },
        {
          "name": "Simulate a second paid order",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 201', () => pm.expect(pm.response.code).to.be.oneOf([201]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.order_id !== undefined) pm.collectionVariables.set('second_order_id', body?.order_id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/orders",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "orders"
              ]
            },
            "description": "`simulateOrder` — Creates a paid delivery order at your test store and sends `order.placed`. Requires a company-wide test key. Sandbox only."
          },
          "response": []
        }
      ]
    },
    {
      "name": "4. Orders",
      "item": [
        {
          "name": "List orders",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders?status=PENDING",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque cursor from a previous page's `next_cursor`.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "PENDING",
                  "description": "",
                  "disabled": false
                },
                {
                  "key": "type",
                  "value": "",
                  "description": "Default: delivery.",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "description": "ISO 8601. Orders with any event since then.",
                  "disabled": true
                }
              ]
            },
            "description": "`listOrders` — Newest first. Use `updated_since` to catch up on anything a missed webhook would have told you."
          },
          "response": []
        },
        {
          "name": "Get an order",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"accepted_via\",\"courier\",\"delivery_fee\",\"external_id\",\"fulfilment_mode\",\"id\",\"lines\",\"payment\",\"placed_at\",\"status\",\"store_id\",\"total_amount\",\"type\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}"
              ]
            },
            "description": "`getOrder` —"
          },
          "response": []
        },
        {
          "name": "Delivery options for an order",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}/delivery-options",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}",
                "delivery-options"
              ]
            },
            "description": "`getDeliveryOptions` — What the store may choose when accepting, with the commission each costs the store."
          },
          "response": []
        },
        {
          "name": "Accept an order",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.collectionVariables.set('accept_key', pm.variables.replaceIn('{{$guid}}'));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"accepted_via\",\"courier\",\"delivery_fee\",\"external_id\",\"fulfilment_mode\",\"id\",\"lines\",\"payment\",\"placed_at\",\"status\",\"store_id\",\"total_amount\",\"type\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{accept_key}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"fulfilment_mode\": \"STORE_STAFF\",\n  \"external_id\": \"BILL-POSTMAN-1\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}/accept",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}",
                "accept"
              ]
            },
            "description": "`acceptOrder` — Accept a PENDING delivery order and choose who delivers it. The store's retailer app can accept too: whichever acts first wins, and the other gets `order_not_in_required_state`."
          },
          "response": []
        },
        {
          "name": "Accept again with the same Idempotency-Key (replayed, not repeated)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"accepted_via\",\"courier\",\"delivery_fee\",\"external_id\",\"fulfilment_mode\",\"id\",\"lines\",\"payment\",\"placed_at\",\"status\",\"store_id\",\"total_amount\",\"type\"]) pm.expect(body, f).to.have.property(f); });",
                  "pm.test('the first answer is replayed', () => pm.expect(pm.response.headers.get('Idempotent-Replayed')).to.eql('true'));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{accept_key}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"fulfilment_mode\": \"STORE_STAFF\",\n  \"external_id\": \"BILL-POSTMAN-1\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}/accept",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}",
                "accept"
              ]
            },
            "description": "`acceptOrder` — Accept a PENDING delivery order and choose who delivers it. The store's retailer app can accept too: whichever acts first wins, and the other gets `order_not_in_required_state`."
          },
          "response": []
        },
        {
          "name": "Reject an order",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"accepted_via\",\"courier\",\"delivery_fee\",\"external_id\",\"fulfilment_mode\",\"id\",\"lines\",\"payment\",\"placed_at\",\"status\",\"store_id\",\"total_amount\",\"type\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"Out of stock\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{second_order_id}}/reject",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{second_order_id}}",
                "reject"
              ]
            },
            "description": "`rejectOrder` — Reject a PENDING delivery order. The customer is refunded and the reserved stock released."
          },
          "response": []
        },
        {
          "name": "Switch to store delivery",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200 or 409', () => pm.expect(pm.response.code).to.be.oneOf([200,409]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"accepted_via\",\"courier\",\"delivery_fee\",\"external_id\",\"fulfilment_mode\",\"id\",\"lines\",\"payment\",\"placed_at\",\"status\",\"store_id\",\"total_amount\",\"type\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"fulfilment_mode\": \"STORE_STAFF\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}/delivery-method",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}",
                "delivery-method"
              ]
            },
            "description": "`changeDeliveryMethod` — Hand a Scanimart-courier order back to the store's own riders -- e.g. no courier could be booked. Any booked courier is cancelled. Only before the order is out for delivery."
          },
          "response": []
        },
        {
          "name": "Retry booking a courier",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 409', () => pm.expect(pm.response.code).to.be.oneOf([409]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('error code is not_courier_order', () => pm.expect(body.error && body.error.code).to.eql('not_courier_order'));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/orders/{{order_id}}/courier/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "orders",
                "{{order_id}}",
                "courier",
                "retry"
              ]
            },
            "description": "`retryCourier` — After `delivery.failed` (no courier available), ask Scanimart to try again.\n\nOnly for orders accepted for SCANIMART_COURIER; this store-staff order is refused."
          },
          "response": []
        }
      ]
    },
    {
      "name": "5. Sandbox: deliver",
      "item": [
        {
          "name": "Simulate Staff app packing",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\",\"status\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"PACKED\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/orders/{{order_id}}/advance",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "orders",
                "{{order_id}}",
                "advance"
              ]
            },
            "description": "`simulateOrderProgress` — Play the store, rider or customer: ACCEPTED (from the retailer app), PACKED, OUT_FOR_DELIVERY, DELIVERED, or CANCELLED (by the customer). Requires a company-wide test key."
          },
          "response": []
        },
        {
          "name": "Move the order out for delivery",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\",\"status\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"OUT_FOR_DELIVERY\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/orders/{{order_id}}/advance",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "orders",
                "{{order_id}}",
                "advance"
              ]
            },
            "description": "`simulateOrderProgress` — Play the store, rider or customer: ACCEPTED (from the retailer app), PACKED, OUT_FOR_DELIVERY, DELIVERED, or CANCELLED (by the customer). Requires a company-wide test key."
          },
          "response": []
        },
        {
          "name": "Move the order to delivered",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\",\"status\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"to\": \"DELIVERED\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/orders/{{order_id}}/advance",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "orders",
                "{{order_id}}",
                "advance"
              ]
            },
            "description": "`simulateOrderProgress` — Play the store, rider or customer: ACCEPTED (from the retailer app), PACKED, OUT_FOR_DELIVERY, DELIVERED, or CANCELLED (by the customer). Requires a company-wide test key."
          },
          "response": []
        }
      ]
    },
    {
      "name": "6. Inventory",
      "item": [
        {
          "name": "Push stock counts",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.collectionVariables.set('now', new Date().toISOString());"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200 or 202', () => pm.expect(pm.response.code).to.be.oneOf([200,202]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"adjusted_for_unbooked_sales\",\"as_of\",\"created\",\"created_at\",\"error_count\",\"errors\",\"finished_at\",\"id\",\"kind\",\"received\",\"status\",\"store_id\",\"unchanged\",\"updated\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.id !== undefined) pm.collectionVariables.set('run_id', body?.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"as_of\": \"{{now}}\",\n  \"items\": [\n    {\n      \"barcode\": \"8901030865278\",\n      \"stock\": 40,\n      \"external_id\": \"SKU-SALT-1\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/inventory",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "inventory"
              ]
            },
            "description": "`pushInventory` — Set the shelf count for up to 1,000 barcodes. Your POS owns the count; Scanimart subtracts the units in its own sales that you had not booked by `as_of` (see `adjusted_for_unbooked_sales`), so a count taken before you booked a Scanimart sale never puts sold stock back on the shelf.\n\nUp to 200 items are applied immediately (200). Larger pushes are queued (202): poll `GET …/inventory/syncs/{id}`. Unknown barcodes need `name`; rows that fail are listed in `errors` and the rest still apply."
          },
          "response": []
        },
        {
          "name": "Adjust stock",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"adjusted_for_unbooked_sales\",\"as_of\",\"created\",\"created_at\",\"error_count\",\"errors\",\"finished_at\",\"id\",\"kind\",\"received\",\"status\",\"store_id\",\"unchanged\",\"updated\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"adjustments\": [\n    {\n      \"barcode\": \"8901030865278\",\n      \"delta\": -1,\n      \"reason\": \"sale\",\n      \"reference\": \"BILL-POSTMAN-2\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/inventory/adjustments",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "inventory",
                "adjustments"
              ]
            },
            "description": "`adjustInventory` — Move stock by a delta per barcode -- a counter sale (−2), a delivery received (+24). Never takes stock below zero. Send an `Idempotency-Key`: an adjustment applied twice is a wrong shelf count."
          },
          "response": []
        },
        {
          "name": "List stock",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/inventory?barcode=8901030865278",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "inventory"
              ],
              "query": [
                {
                  "key": "barcode",
                  "value": "8901030865278",
                  "description": "",
                  "disabled": false
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque cursor from a previous page's `next_cursor`.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                }
              ]
            },
            "description": "`listInventory` — Stock as Scanimart sees it, with units reserved for paid online orders."
          },
          "response": []
        },
        {
          "name": "List recent stock pushes",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/inventory/syncs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "inventory",
                "syncs"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                }
              ]
            },
            "description": "`listInventorySyncs` —"
          },
          "response": []
        },
        {
          "name": "Get a stock push",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"adjusted_for_unbooked_sales\",\"as_of\",\"created\",\"created_at\",\"error_count\",\"errors\",\"finished_at\",\"id\",\"kind\",\"received\",\"status\",\"store_id\",\"unchanged\",\"updated\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/inventory/syncs/{{run_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "inventory",
                "syncs",
                "{{run_id}}"
              ]
            },
            "description": "`getInventorySync` —"
          },
          "response": []
        }
      ]
    },
    {
      "name": "7. Sales and events",
      "item": [
        {
          "name": "List completed sales",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });",
                  "const sale = (body.data || []).find((s) => s.id === pm.collectionVariables.get('order_id')) || (body.data || [])[0];",
                  "if (sale) pm.collectionVariables.set('event_id', sale.event_id);",
                  "pm.test('the delivered order is a sale', () => pm.expect(sale, 'no sales').to.be.an('object'));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/sales",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "sales"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque cursor from a previous page's `next_cursor`.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                },
                {
                  "key": "since",
                  "value": "",
                  "description": "ISO 8601.",
                  "disabled": true
                }
              ]
            },
            "description": "`listSales` — Every Scanimart sale at the store -- delivered online orders and paid in-store Scan & Go -- oldest first, for booking into your POS. The same sales arrive as `sale.completed` webhooks; this is the pull fallback. Covers the last 30 days."
          },
          "response": []
        },
        {
          "name": "Acknowledge booked sales",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"acknowledged\",\"unknown\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event_ids\": [\n    \"{{event_id}}\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/sales/ack",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "sales",
                "ack"
              ]
            },
            "description": "`acknowledgeSales` — For integrations that pull sales instead of receiving webhooks: tell Scanimart which sales you have booked, so stock you push afterwards is not adjusted for them. A 2xx to a `sale.completed` webhook does this automatically."
          },
          "response": []
        },
        {
          "name": "List events",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/events?store_id={{store_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "events"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque cursor from a previous page's `next_cursor`.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                },
                {
                  "key": "since",
                  "value": "",
                  "description": "ISO 8601.",
                  "disabled": true
                },
                {
                  "key": "store_id",
                  "value": "{{store_id}}",
                  "description": "",
                  "disabled": false
                },
                {
                  "key": "type",
                  "value": "",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "description": "`listEvents` — Order events at your connected stores, oldest first -- the same bodies webhooks carry. Use it to recover anything your endpoint missed. Covers the last 30 days."
          },
          "response": []
        }
      ]
    },
    {
      "name": "8. Webhook endpoints",
      "item": [
        {
          "name": "Add a webhook endpoint",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 201', () => pm.expect(pm.response.code).to.be.oneOf([201]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"created_at\",\"description\",\"disabled_reason\",\"events\",\"id\",\"mode\",\"status\",\"url\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.id !== undefined) pm.collectionVariables.set('endpoint_id', body?.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Retrying with the same value returns the first answer instead of acting twice."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"{{webhook_url}}\",\n  \"description\": \"Postman\",\n  \"events\": [\n    \"order.placed\",\n    \"sale.completed\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints"
              ]
            },
            "description": "`createWebhookEndpoint` — The response includes the signing `secret`, shown only now and when rolled."
          },
          "response": []
        },
        {
          "name": "List webhook endpoints",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints"
              ]
            },
            "description": "`listWebhookEndpoints` —"
          },
          "response": []
        },
        {
          "name": "Get a webhook endpoint",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"created_at\",\"description\",\"disabled_reason\",\"events\",\"id\",\"mode\",\"status\",\"url\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}"
              ]
            },
            "description": "`getWebhookEndpoint` — Looks up one of the caller's endpoints. Holds no handlers itself: the\nsub-resource views (roll-secret, test, deliveries) inherit only this, never\nthe detail view's GET/PATCH/DELETE -- otherwise DELETE .../test would\ndelete the endpoint."
          },
          "response": []
        },
        {
          "name": "Update a webhook endpoint",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"created_at\",\"description\",\"disabled_reason\",\"events\",\"id\",\"mode\",\"status\",\"url\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"description\": \"Postman (updated)\",\n  \"events\": []\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}"
              ]
            },
            "description": "`updateWebhookEndpoint` — Setting `status` to ACTIVE re-enables an endpoint that was switched off after repeated failures."
          },
          "response": []
        },
        {
          "name": "Roll the signing secret",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"created_at\",\"description\",\"disabled_reason\",\"events\",\"id\",\"mode\",\"status\",\"url\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}/roll-secret",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}",
                "roll-secret"
              ]
            },
            "description": "`rollWebhookSecret` — The old secret stops working immediately. Update your receiver before calling this."
          },
          "response": []
        },
        {
          "name": "Send a test event",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"attempts\",\"created_at\",\"event_id\",\"event_type\",\"id\",\"last_error\",\"last_status_code\",\"next_attempt_at\",\"status\",\"succeeded_at\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"ping\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}",
                "test"
              ]
            },
            "description": "`sendTestEvent` — Sends one event to this endpoint now and reports how it answered. With `bad_signature: true` the signature is deliberately wrong -- a correct receiver answers 4xx (this is on the go-live checklist)."
          },
          "response": []
        },
        {
          "name": "List deliveries to an endpoint",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"data\",\"has_more\",\"next_cursor\"]) pm.expect(body, f).to.have.property(f); });",
                  "if (body?.data?.[0]?.id !== undefined) pm.collectionVariables.set('delivery_id', body?.data?.[0]?.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}/deliveries",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}",
                "deliveries"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "",
                  "description": "Opaque cursor from a previous page's `next_cursor`.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "Page size, 1–100. Default 50.",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "description": "`listWebhookDeliveries` — Looks up one of the caller's endpoints. Holds no handlers itself: the\nsub-resource views (roll-secret, test, deliveries) inherit only this, never\nthe detail view's GET/PATCH/DELETE -- otherwise DELETE .../test would\ndelete the endpoint."
          },
          "response": []
        },
        {
          "name": "Retry a delivery now",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"attempts\",\"created_at\",\"event_id\",\"event_type\",\"id\",\"last_error\",\"last_status_code\",\"next_attempt_at\",\"status\",\"succeeded_at\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-deliveries/{{delivery_id}}/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-deliveries",
                "{{delivery_id}}",
                "retry"
              ]
            },
            "description": "`retryWebhookDelivery` — Re-sends a failed or given-up delivery straight away."
          },
          "response": []
        },
        {
          "name": "Delete a webhook endpoint",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 204', () => pm.expect(pm.response.code).to.be.oneOf([204]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));"
                ]
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/webhook-endpoints/{{endpoint_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "webhook-endpoints",
                "{{endpoint_id}}"
              ]
            },
            "description": "`deleteWebhookEndpoint` — Looks up one of the caller's endpoints. Holds no handlers itself: the\nsub-resource views (roll-secret, test, deliveries) inherit only this, never\nthe detail view's GET/PATCH/DELETE -- otherwise DELETE .../test would\ndelete the endpoint."
          },
          "response": []
        }
      ]
    },
    {
      "name": "9. Sandbox: in-store sale and reset",
      "item": [
        {
          "name": "Simulate an in-store Scan & Go sale",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 201', () => pm.expect(pm.response.code).to.be.oneOf([201]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"order_id\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"lines\": [\n    {\n      \"barcode\": \"8901030865278\",\n      \"quantity\": 1\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/sandbox/instore-sales",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "instore-sales"
              ]
            },
            "description": "`simulateInstoreSale` — Requires a company-wide test key."
          },
          "response": []
        },
        {
          "name": "Reset the test store",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"deleted_orders\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/sandbox/reset",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sandbox",
                "reset"
              ]
            },
            "description": "`resetSandbox` — Deletes the test store's orders and restores every product to 50 units. Requires a company-wide test key."
          },
          "response": []
        }
      ]
    },
    {
      "name": "10. Not run by default",
      "item": [
        {
          "name": "Disconnect a store",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.variables.get('run_destructive') !== '1') { pm.execution.skipRequest(); }"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('status is 200', () => pm.expect(pm.response.code).to.be.oneOf([200]));",
                  "pm.test('Request-Id is set', () => pm.expect(pm.response.headers.get('Request-Id')).to.match(/^req_/));",
                  "const body = pm.response.code === 204 ? {} : pm.response.json();",
                  "pm.test('documented fields are present', () => { for (const f of [\"connected_at\",\"id\",\"store\"]) pm.expect(body, f).to.have.property(f); });"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/stores/{{store_id}}/disconnect",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "stores",
                "{{store_id}}",
                "disconnect"
              ]
            },
            "description": "`disconnectStore` — Stops all events for the store and revokes your access to it. The store can reconnect with a new code.\n\nDisconnects the store from your company. Skipped unless the `run_destructive` variable is 1 -- in the sandbox, Set up sandbox in the dashboard reconnects the test store."
          },
          "response": []
        }
      ]
    }
  ]
}
