{
  "info": {
    "name": "Harmon Storefront API",
    "_postman_id": "harmon-storefront-api",
    "description": "The **Harmon Storefront API** is a public, machine-authenticated read + commerce\nAPI for building your own ecommerce site on Harmon.\n\n* **Authentication** — every call carries a tenant-scoped API key as\n  `Authorization: Bearer hk_…`. A **publishable** key (browser-safe) authorizes\n  anonymous catalog reads + initiating shopper auth; a **secret** key\n  (server-side only) additionally authorizes customer-scoped reads, checkout, and\n  webhook management. Customer-scoped routes also require a **shopper token** in\n  the `X-Storefront-Shopper-Token` header.\n* **Modes** — a key prefixed `hk_test_` runs in **sandbox** mode; every other key\n  is **live**. The mode is echoed in the `X-Harmon-Mode` response header.\n* **Caching** — catalog reads return a strong `ETag` + `Cache-Control`; send\n  `If-None-Match` to revalidate (`304`).\n* **Errors** - every hard error returns `{ \"error\": { \"code\", \"message\", ... } }`;\n  branch on the stable `error.code` (`unauthorized` / `forbidden` / `not_found` /\n  `conflict` / `validation_error` / `rate_limited` / `bad_gateway` / ...). The\n  legacy top-level `detail` is still mirrored for one release.\n* **Money** - every money field is a JSON **number** in the row's ISO-4217\n  `currency` (there are no integer cents); an unknown amount is `null`, never\n  `0`. Rate fields (`effective_gct_rate`) are fractions (`0.15` == 15%), distinct\n  from amount fields (`gct_amount`).\n* **Webhooks** — outbound events are signed `X-Harmon-Signature: sha256=<hmac>`;\n  verify against your subscription's signing secret.\n* **Rate limits** — each key is limited per minute; over the limit returns `429`\n  with `Retry-After`.\n\nSee the [merchant integration guide](https://github.com/harmon/docs) for the full\ncontract, error model, and signature-verification snippets.\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.harmoncommerce.com",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "health",
      "item": [
        {
          "name": "Health",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/health",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "health"
              ]
            },
            "description": "Health"
          }
        }
      ]
    },
    {
      "name": "diagnostics",
      "item": [
        {
          "name": "Ping",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/ping",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "ping"
              ]
            },
            "description": "Ping"
          }
        }
      ]
    },
    {
      "name": "catalog",
      "item": [
        {
          "name": "List Products",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/products",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "products"
              ]
            },
            "description": "The anonymous catalog page (list price + tax + coarse availability).\n\n**Customer pricing (decision 0.2, ALLOW):** a **publishable** key presenting a\n**valid** ``X-Storefront-Shopper-Token`` receives the customer-priced catalog -\nthe publishable key identifies the integration/tenant and the shopper token is\nthe customer's own credential (tenant stays key-derived, customer token-derived;\nInvariant 3). Such a response is ``Cache-Control: private`` and ``Vary``s on the\nshopper-token header so a negotiated price never lands in a shared/anonymous\ncache entry. An absent token is the normal anonymous (list-price) path; a\npresent-but-**invalid** token fails closed (401/403), never a silent downgrade."
          }
        },
        {
          "name": "Get Product",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/products/:sku",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "products",
                ":sku"
              ],
              "variable": [
                {
                  "key": "sku",
                  "value": "",
                  "description": "Path parameter: sku"
                }
              ]
            },
            "description": "Get Product"
          }
        },
        {
          "name": "List Categories",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/categories",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "categories"
              ]
            },
            "description": "The tenant category tree. A strong-ETag, ``public`` cacheable GET\n(storefront-cleanup plan Phase 5.3): send ``If-None-Match`` to revalidate\n(``304``). The taxonomy is customer-independent, so it is always ``public``."
          }
        },
        {
          "name": "List Tags",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/tags",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "tags"
              ]
            },
            "description": "The tenant's grouped tag taxonomy - the faceted counterpart to\n``GET /v1/categories`` (storefront-cleanup plan Phase 5.1). Sourced from\ninventory; a strong-ETag, ``public`` cacheable GET consistent with categories\n(Phase 5.3)."
          }
        }
      ]
    },
    {
      "name": "availability",
      "item": [
        {
          "name": "Product Availability",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/products/:sku/availability",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "products",
                ":sku",
                "availability"
              ],
              "variable": [
                {
                  "key": "sku",
                  "value": "",
                  "description": "Path parameter: sku"
                }
              ]
            },
            "description": "One SKU's coarse availability band. A strong-ETag, ``public`` cacheable GET\n(storefront-cleanup plan Phase 5.3): the band is customer-independent, so send\n``If-None-Match`` to revalidate (``304``). The multi-SKU batch is a POST and is\nnot cacheable."
          }
        },
        {
          "name": "Availability Batch",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/availability/batch",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "availability",
                "batch"
              ]
            },
            "description": "Availability Batch"
          }
        }
      ]
    },
    {
      "name": "customer",
      "item": [
        {
          "name": "Get Me",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/me",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "me"
              ]
            },
            "description": "Get Me"
          }
        },
        {
          "name": "Get Credit Status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/me/credit-status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "me",
                "credit-status"
              ]
            },
            "description": "Get Credit Status"
          }
        }
      ]
    },
    {
      "name": "cart",
      "item": [
        {
          "name": "Create Cart",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts"
              ]
            },
            "description": "Create Cart"
          }
        },
        {
          "name": "Get Cart",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                }
              ]
            },
            "description": "Get Cart"
          }
        },
        {
          "name": "Add Line",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id/lines",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id",
                "lines"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                }
              ]
            },
            "description": "Add Line"
          }
        },
        {
          "name": "Update Line",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id/lines/:line_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id",
                "lines",
                ":line_id"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                },
                {
                  "key": "line_id",
                  "value": "",
                  "description": "Path parameter: line_id"
                }
              ]
            },
            "description": "Update Line"
          }
        },
        {
          "name": "Remove Line",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id/lines/:line_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id",
                "lines",
                ":line_id"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                },
                {
                  "key": "line_id",
                  "value": "",
                  "description": "Path parameter: line_id"
                }
              ]
            },
            "description": "Remove Line"
          }
        },
        {
          "name": "Price Cart",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id/price",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id",
                "price"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                }
              ]
            },
            "description": "Price Cart"
          }
        },
        {
          "name": "Apply Promotion",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/carts/:cart_id/promotions",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "carts",
                ":cart_id",
                "promotions"
              ],
              "variable": [
                {
                  "key": "cart_id",
                  "value": "",
                  "description": "Path parameter: cart_id"
                }
              ]
            },
            "description": "Apply Promotion"
          }
        }
      ]
    },
    {
      "name": "checkout",
      "item": [
        {
          "name": "Shipping Options",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/checkout/shipping-options",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "checkout",
                "shipping-options"
              ]
            },
            "description": "The tenant's enabled shipping options for the checkout step (courier-\nfulfilment plan Phase 4.2). Empty (and ``couriers_enabled=False``) for a\ntenant that never opted in, so the storefront renders no shipping step and\nrequires no carrier selection at placement (Invariant 8)."
          }
        },
        {
          "name": "Checkout",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/checkout",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "checkout"
              ]
            },
            "description": "Checkout"
          }
        },
        {
          "name": "Repay",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/checkout/:order_id/repay",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "checkout",
                ":order_id",
                "repay"
              ],
              "variable": [
                {
                  "key": "order_id",
                  "value": "",
                  "description": "Path parameter: order_id"
                }
              ]
            },
            "description": "Re-open payment for a still-held order whose session expired/failed/was\ncancelled (storefront-cleanup plan Phase 4.1).\n\nLooks up the order's persisted payment-session link scoped to the token's\ntenant + customer (an unknown / cross-customer order 404s, no existence leak,\nInvariant 3). A still-held order (``PENDING_PAYMENT``) whose session is dead\ngets a fresh session + gateway redirect; a paid/confirmed order does not\nre-open one (409). When a fresh session is minted the link is re-pointed to it\nso ``payment-status`` polling follows the live session."
          }
        },
        {
          "name": "Payment Status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/checkout/:order_id/payment-status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "checkout",
                ":order_id",
                "payment-status"
              ],
              "variable": [
                {
                  "key": "order_id",
                  "value": "",
                  "description": "Path parameter: order_id"
                }
              ]
            },
            "description": "Poll the payment session opened for a prepaid order (plan Phase 5.2).\n\nA thin proxy of the payments-service session status the shopper SPA polls\nafter the gateway return. The order → session link is looked up scoped to the\ntoken's tenant + customer, so an unknown order — or one belonging to another\ncustomer — 404s with no existence leak (Invariant 8). The webhook remains the\nsource of truth; this read never mutates ledger state (Invariant 3)."
          }
        }
      ]
    },
    {
      "name": "orders",
      "item": [
        {
          "name": "List Orders",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/orders",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "orders"
              ]
            },
            "description": "List Orders"
          }
        },
        {
          "name": "Get Order",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/orders/:order_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "orders",
                ":order_id"
              ],
              "variable": [
                {
                  "key": "order_id",
                  "value": "",
                  "description": "Path parameter: order_id"
                }
              ]
            },
            "description": "Get Order"
          }
        },
        {
          "name": "Cancel",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/orders/:order_id/cancel",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "orders",
                ":order_id",
                "cancel"
              ],
              "variable": [
                {
                  "key": "order_id",
                  "value": "",
                  "description": "Path parameter: order_id"
                }
              ]
            },
            "description": "Cancel"
          }
        }
      ]
    },
    {
      "name": "invoices",
      "item": [
        {
          "name": "List Invoices",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/invoices",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "invoices"
              ]
            },
            "description": "List Invoices"
          }
        },
        {
          "name": "Get Invoice",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/invoices/:invoice_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "invoices",
                ":invoice_id"
              ],
              "variable": [
                {
                  "key": "invoice_id",
                  "value": "",
                  "description": "Path parameter: invoice_id"
                }
              ]
            },
            "description": "Get Invoice"
          }
        },
        {
          "name": "Pay Invoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/invoices/:invoice_id/pay",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "invoices",
                ":invoice_id",
                "pay"
              ],
              "variable": [
                {
                  "key": "invoice_id",
                  "value": "",
                  "description": "Path parameter: invoice_id"
                }
              ]
            },
            "description": "Open a gateway payment session for one of the customer's own open invoices\n(storefront-cleanup plan Phase 4.2). A paid/voided invoice 409s; a missing /\ncross-customer invoice 404s (OMS scope, no existence leak); a tenant without\nonline payments enabled 403s (payments-service gate)."
          }
        },
        {
          "name": "Get Invoice Pdf",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/invoices/:invoice_id/pdf",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "invoices",
                ":invoice_id",
                "pdf"
              ],
              "variable": [
                {
                  "key": "invoice_id",
                  "value": "",
                  "description": "Path parameter: invoice_id"
                }
              ]
            },
            "description": "Stream the customer's own invoice as a PDF, rendered on demand\n(document-generation plan Phase 3.4).\n\nComposes the fully-resolved payload from the customer-scoped invoice/order\nread + tenant branding, POSTs it to the stateless documents service, and\nstreams back ``application/pdf``. ``?download=1`` switches the disposition to\n``attachment``; the default ``inline`` opens it in a browser tab. A missing\nor cross-customer invoice 404s (OMS scope) and never renders."
          }
        }
      ]
    },
    {
      "name": "webhooks",
      "item": [
        {
          "name": "List Subscriptions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks"
              ]
            },
            "description": "List Subscriptions"
          }
        },
        {
          "name": "Create Subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks"
              ]
            },
            "description": "Create Subscription"
          }
        },
        {
          "name": "Get Subscription",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/:subscription_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                ":subscription_id"
              ],
              "variable": [
                {
                  "key": "subscription_id",
                  "value": "",
                  "description": "Path parameter: subscription_id"
                }
              ]
            },
            "description": "Get Subscription"
          }
        },
        {
          "name": "Update Subscription",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/:subscription_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                ":subscription_id"
              ],
              "variable": [
                {
                  "key": "subscription_id",
                  "value": "",
                  "description": "Path parameter: subscription_id"
                }
              ]
            },
            "description": "Patch a subscription's endpoint / events / status (storefront-cleanup plan\nPhase 6.5 - brings the public merchant surface to parity with the staff\n``/internal/admin/webhooks`` PATCH). 404 when it is not the key's tenant; the\nread response carries no secret (rotate to mint a new one)."
          }
        },
        {
          "name": "Rotate Subscription Secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/:subscription_id/rotate-secret",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                ":subscription_id",
                "rotate-secret"
              ],
              "variable": [
                {
                  "key": "subscription_id",
                  "value": "",
                  "description": "Path parameter: subscription_id"
                }
              ]
            },
            "description": "Mint a fresh reveal-once ``signing_secret`` for a subscription\n(storefront-cleanup plan Phase 6.5; the schema already hinted rotation). The\nnew secret is returned **once** here and never re-read; the old one stops\nverifying immediately. 404 cross-tenant (no existence leak)."
          }
        },
        {
          "name": "Disable Subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/:subscription_id/disable",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                ":subscription_id",
                "disable"
              ],
              "variable": [
                {
                  "key": "subscription_id",
                  "value": "",
                  "description": "Path parameter: subscription_id"
                }
              ]
            },
            "description": "Disable Subscription"
          }
        },
        {
          "name": "Ping Subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhooks/:subscription_id/ping",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhooks",
                ":subscription_id",
                "ping"
              ],
              "variable": [
                {
                  "key": "subscription_id",
                  "value": "",
                  "description": "Path parameter: subscription_id"
                }
              ]
            },
            "description": "Ping Subscription"
          }
        }
      ]
    }
  ]
}
