{"openapi":"3.1.0","info":{"title":"SellStein Merchant API","version":"v1","summary":"Public REST API for SellStein merchants.","description":"The SellStein Merchant API lets you manage products, orders, customers, discount codes, and read analytics for a single business programmatically.\n\n**Authentication.** Every request is authenticated with a secret API key sent as a Bearer token. Generate keys in the dashboard at `/app/api-docs`. The key encodes the business it belongs to — there is no separate business id in the path.\n\n**Money is always in minor units.** All monetary amounts (`price`, `total`, `subtotal`, discount `value` for fixed codes, etc.) are integers in the currency's smallest unit. For USD that is cents: `1999` means `$19.99`. Never send decimals.\n\n**Scopes.** Each endpoint requires a scope that the key must carry. A key with insufficient scope receives `403 forbidden` with the missing scope in `required`.\n\n**Rate limit.** 30 requests per minute, per API key, enforced consistently across every edge. Responses carry `X-RateLimit-*` headers; a `429 rate_limited` is returned when exceeded.\n\n**Pagination.** List endpoints return `{ data, page, limit, has_more }`. `has_more` is `true` when the page came back full (`data.length === limit`); request the next page to continue.\n\n**IDs** are opaque 21-character URL-safe strings (nanoid). Do not parse them.","contact":{"name":"SellStein Developer Support","url":"https://sellstein.com/contact","email":"support@sellstein.com"},"license":{"name":"Proprietary — © Fluxera LLC","url":"https://sellstein.com/legal/terms"}},"externalDocs":{"description":"Human-readable API reference","url":"https://sellstein.com/docs"},"servers":[{"url":"https://api.sellstein.com","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Products","description":"Create, read, update, and delete products. Prices are in minor units."},{"name":"Orders","description":"Read orders and update their status / fulfillment. Orders are created by checkout, never via this API."},{"name":"Customers","description":"Read customers and their recent orders. PII (email, name, phone) is decrypted on read."},{"name":"Discounts","description":"Read discount codes. Read-only."},{"name":"Analytics","description":"Aggregate store metrics. Read-only."}],"paths":{"/api/v1/products":{"get":{"tags":["Products"],"operationId":"listProducts","summary":"List products","description":"Returns a paginated list of products for the authenticated business, newest first.\n\n**Required scope:** `products:read`","x-scope":"products:read","x-read-only":true,"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","required":false,"description":"Filter by product status (e.g. `draft`, `active`, `archived`). Omit to return all statuses.","schema":{"type":"string","example":"active"}}],"responses":{"200":{"description":"A page of products.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}}]},"example":{"data":[{"id":"V1StGXR8_Z5jdHi6B-myT","business_id":"biz_8KdLmNpQ","name":"Pro License — Lifetime","slug":"pro-license-lifetime","description":"One-time purchase, lifetime updates.","price":14900,"compare_at_price":19900,"currency":"usd","product_type":"digital","status":"active","images":["https://cdn.sellstein.com/p/pro-license.png"],"variants":null,"weight":null,"requires_shipping":0,"inventory_count":null,"inventory_tracking":0,"category_id":null,"sort_order":0,"metadata":{"sku":"PRO-LT"},"created_at":"2026-05-21T14:03:11.000Z","updated_at":"2026-06-01T09:12:44.000Z"}],"page":1,"limit":25,"has_more":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Products"],"operationId":"createProduct","summary":"Create a product","description":"Creates a new product. `price` and `compare_at_price` must be **integers in minor units** (cents) — sending `19.99` is rejected; send `1999`.\n\nA `slug` is auto-generated from `name` if omitted. Subject to your plan's product limit (`403 plan_limit_exceeded` when reached).\n\n**Required scope:** `products:write`","x-scope":"products:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreate"},"example":{"name":"Pro License — Lifetime","description":"One-time purchase, lifetime updates.","price":14900,"compare_at_price":19900,"currency":"usd","product_type":"digital","status":"active","images":["https://cdn.sellstein.com/p/pro-license.png"],"metadata":{"sku":"PRO-LT"}}}}},"responses":{"201":{"description":"Product created. Returns the stored row (JSON columns are returned as raw strings here, exactly as persisted).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Product"}},"required":["data"]},"example":{"data":{"id":"kd9aL2mZ8QpRsTuVwXyZ1","business_id":"biz_8KdLmNpQ","name":"Pro License — Lifetime","slug":"pro-license-lifetime","description":"One-time purchase, lifetime updates.","price":14900,"compare_at_price":19900,"currency":"usd","product_type":"digital","status":"active","images":"[\"https://cdn.sellstein.com/p/pro-license.png\"]","variants":null,"requires_shipping":0,"inventory_tracking":0,"sort_order":0,"metadata":"{\"sku\":\"PRO-LT\"}","created_at":"2026-06-05T10:00:00.000Z","updated_at":"2026-06-05T10:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenOrPlanLimit"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/products/{id}":{"parameters":[{"$ref":"#/components/parameters/ProductId"}],"get":{"tags":["Products"],"operationId":"getProduct","summary":"Retrieve a product","description":"Returns a single product. `images`, `variants`, and `metadata` are parsed from JSON into objects on this endpoint.\n\n**Required scope:** `products:read`","x-scope":"products:read","x-read-only":true,"responses":{"200":{"description":"The product.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Product"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"put":{"tags":["Products"],"operationId":"updateProduct","summary":"Update a product","description":"Partially updates a product. Only the fields you include are changed; everything else is left as-is. Integer fields (`price`, `compare_at_price`, `weight`, `inventory_count`, `sort_order`) must be minor-unit integers.\n\n**Required scope:** `products:write`","x-scope":"products:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUpdate"},"example":{"price":12900,"status":"active"}}}},"responses":{"200":{"description":"Updated product (stored row).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Product"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Products"],"operationId":"deleteProduct","summary":"Delete a product","description":"Permanently deletes a product and cleans up orphaned references (discount targets, subscription plans, reviews are nulled). This is destructive and requires the dedicated `products:delete` scope — a `products:write` key cannot delete.\n\n**Required scope:** `products:delete`","x-scope":"products:delete","responses":{"200":{"description":"Product deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"},"example":{"success":true,"deleted":"V1StGXR8_Z5jdHi6B-myT"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"The key lacks the `products:delete` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Insufficient permissions","code":"forbidden","required":"products:delete"}}}},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/orders":{"get":{"tags":["Orders"],"operationId":"listOrders","summary":"List orders","description":"Returns a paginated list of orders, newest first. `shipping_address` and `billing_address` are parsed from JSON into objects.\n\n**Required scope:** `orders:read`","x-scope":"orders:read","x-read-only":true,"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","required":false,"description":"Filter by order status (`pending`, `confirmed`, `processing`, `shipped`, `delivered`, `cancelled`, `refunded`).","schema":{"type":"string","example":"delivered"}}],"responses":{"200":{"description":"A page of orders.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}}}]},"example":{"data":[{"id":"ord7Hn2KpQ9rStUvWxYz0","business_id":"biz_8KdLmNpQ","order_number":1042,"customer_id":"cstAb3Cd4Ef5Gh6Ij7Kl8","customer_email":"buyer@example.com","customer_name":"Jane Buyer","status":"delivered","fulfillment_status":"fulfilled","payment_status":"paid","subtotal":14900,"discount_total":0,"tax_total":0,"shipping_total":0,"total":14900,"currency":"usd","shipping_address":null,"billing_address":{"country":"US","postal_code":"10001"},"source":"checkout","created_at":"2026-06-02T18:24:55.000Z","updated_at":"2026-06-02T18:25:10.000Z"}],"page":1,"limit":25,"has_more":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/orders/{id}":{"parameters":[{"$ref":"#/components/parameters/OrderId"}],"get":{"tags":["Orders"],"operationId":"getOrder","summary":"Retrieve an order","description":"Returns a single order including its line `items`. Addresses and each item's `variant_info` are parsed from JSON.\n\n**Required scope:** `orders:read`","x-scope":"orders:read","x-read-only":true,"responses":{"200":{"description":"The order with items.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Order"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}}}}]}},"required":["data"]},"example":{"data":{"id":"ord7Hn2KpQ9rStUvWxYz0","business_id":"biz_8KdLmNpQ","order_number":1042,"customer_email":"buyer@example.com","status":"delivered","fulfillment_status":"fulfilled","payment_status":"paid","subtotal":14900,"total":14900,"currency":"usd","shipping_address":null,"billing_address":{"country":"US","postal_code":"10001"},"items":[{"id":"itm9Lm0NpQ1rStUvWxYz2","order_id":"ord7Hn2KpQ9rStUvWxYz0","product_id":"V1StGXR8_Z5jdHi6B-myT","product_name":"Pro License — Lifetime","variant_info":null,"quantity":1,"unit_price":14900,"total":14900,"source":"direct","created_at":"2026-06-02T18:24:55.000Z"}],"created_at":"2026-06-02T18:24:55.000Z","updated_at":"2026-06-02T18:25:10.000Z"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/orders/{id}/status":{"parameters":[{"$ref":"#/components/parameters/OrderId"}],"put":{"tags":["Orders"],"operationId":"updateOrderStatus","summary":"Update order status","description":"Updates one or more of an order's status fields and/or notes. Send only the fields you want to change.\n\n**Important:** `payment_status` can be set to `pending`, `refunded`, or `failed` only — you **cannot** set it to `paid` via the API. The transition to `paid` happens exclusively through verified payment webhooks.\n\n**Required scope:** `orders:write`","x-scope":"orders:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderStatusUpdate"},"example":{"status":"shipped","fulfillment_status":"fulfilled","notes":"Tracking: 1Z999AA10123456784"}}}},"responses":{"200":{"description":"Updated order (addresses parsed from JSON).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}},"required":["data"]}}}},"400":{"description":"An invalid status value was supplied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Invalid status. Must be one of: pending, confirmed, processing, shipped, delivered, cancelled, refunded","code":"validation_error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/customers":{"get":{"tags":["Customers"],"operationId":"listCustomers","summary":"List customers","description":"Returns a paginated list of customers, newest first. Email, name, and phone are decrypted before being returned. Pass `search` to filter by email or name substring (case-insensitive).\n\n**Required scope:** `customers:read`","x-scope":"customers:read","x-read-only":true,"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"search","in":"query","required":false,"description":"Case-insensitive substring match against customer email or name.","schema":{"type":"string","example":"jane"}}],"responses":{"200":{"description":"A page of customers.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}}}}]},"example":{"data":[{"id":"cstAb3Cd4Ef5Gh6Ij7Kl8","business_id":"biz_8KdLmNpQ","email":"jane@example.com","name":"Jane Buyer","first_name":"Jane","last_name":"Buyer","phone":"+12015550123","total_orders":3,"total_spent":44700,"store_credit_balance":0,"created_at":"2026-04-10T11:00:00.000Z","updated_at":"2026-06-02T18:25:10.000Z"}],"page":1,"limit":25,"has_more":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/customers/{id}":{"parameters":[{"$ref":"#/components/parameters/CustomerId"}],"get":{"tags":["Customers"],"operationId":"getCustomer","summary":"Retrieve a customer","description":"Returns a single customer (PII decrypted) plus up to 10 of their most recent orders in `recent_orders`.\n\n**Required scope:** `customers:read`","x-scope":"customers:read","x-read-only":true,"responses":{"200":{"description":"The customer with recent orders.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Customer"},{"type":"object","properties":{"recent_orders":{"type":"array","items":{"$ref":"#/components/schemas/RecentOrder"}}}}]}},"required":["data"]},"example":{"data":{"id":"cstAb3Cd4Ef5Gh6Ij7Kl8","business_id":"biz_8KdLmNpQ","email":"jane@example.com","name":"Jane Buyer","phone":"+12015550123","total_orders":3,"total_spent":44700,"recent_orders":[{"id":"ord7Hn2KpQ9rStUvWxYz0","order_number":1042,"status":"delivered","total":14900,"currency":"usd","created_at":"2026-06-02T18:24:55.000Z"}],"created_at":"2026-04-10T11:00:00.000Z","updated_at":"2026-06-02T18:25:10.000Z"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/discounts":{"get":{"tags":["Discounts"],"operationId":"listDiscounts","summary":"List discount codes","description":"Returns a paginated list of discount codes, newest first. Read-only.\n\nFor `type: \"percentage\"`, `value` is a whole-number percent (e.g. `10` = 10% off). For `type: \"fixed\"`, `value` is an amount in minor units in the code's `currency` (e.g. `500` = $5.00 off).\n\n**Required scope:** `products:read`","x-scope":"products:read","x-read-only":true,"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"A page of discount codes.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}}}}]},"example":{"data":[{"id":"dscMn5Op6Qr7St8Uv9Wx0","business_id":"biz_8KdLmNpQ","code":"LAUNCH10","type":"percentage","value":10,"currency":"usd","product_id":null,"applies_to":"all","min_order_amount":null,"max_uses":100,"used_count":12,"expires_at":"2026-07-31T23:59:59.000Z","active":1,"created_at":"2026-05-01T08:00:00.000Z","updated_at":"2026-05-01T08:00:00.000Z"}],"page":1,"limit":25,"has_more":false}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/analytics/summary":{"get":{"tags":["Analytics"],"operationId":"getAnalyticsSummary","summary":"Analytics summary","description":"Returns an at-a-glance summary of the store. `total_revenue` counts paid orders only (`payment_status = 'paid'`) and is in minor units. Read-only.\n\n**Required scope:** `orders:read`","x-scope":"orders:read","x-read-only":true,"responses":{"200":{"description":"Store summary.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AnalyticsSummary"}},"required":["data"]},"example":{"data":{"total_orders":1042,"paid_orders":987,"total_revenue":14702300,"total_customers":612,"total_products":24,"active_products":19}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenScope"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sk_<biz8>_<random>","description":"Secret API key sent as `Authorization: Bearer sk_...`. The key format is `sk_` + the first 8 characters of the business id + `_` + a random token (e.g. `sk_2f9a1c3e_8KdLmNpQrStUvWx`). Keys are shown in full exactly once at creation; only a prefix is stored afterward. Manage keys in the dashboard at `/app/api-docs`."}},"parameters":{"Page":{"name":"page","in":"query","required":false,"description":"1-based page number. Defaults to 1.","schema":{"type":"integer","minimum":1,"default":1,"example":1}},"Limit":{"name":"limit","in":"query","required":false,"description":"Items per page. Defaults to 25, clamped to the range 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"example":25}},"ProductId":{"name":"id","in":"path","required":true,"description":"The product id.","schema":{"type":"string","example":"V1StGXR8_Z5jdHi6B-myT"}},"OrderId":{"name":"id","in":"path","required":true,"description":"The order id (the opaque `id`, not the human `order_number`).","schema":{"type":"string","example":"ord7Hn2KpQ9rStUvWxYz0"}},"CustomerId":{"name":"id","in":"path","required":true,"description":"The customer id.","schema":{"type":"string","example":"cstAb3Cd4Ef5Gh6Ij7Kl8"}}},"headers":{"RateLimitLimit":{"description":"The request ceiling for the current window (always `30`).","schema":{"type":"integer","example":30}},"RateLimitRemaining":{"description":"Requests remaining in the current 60-second window.","schema":{"type":"integer","example":29}},"RateLimitReset":{"description":"Seconds until the window resets. Present on `429` responses.","schema":{"type":"integer","example":42}},"RetryAfter":{"description":"Seconds to wait before retrying. Present on `429` responses.","schema":{"type":"integer","example":42}}},"responses":{"Unauthorized":{"description":"The API key is missing, malformed, revoked, expired, or the account is suspended.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"No Authorization header","value":{"error":"Missing API key","code":"auth_required"}},"invalid":{"summary":"Unknown or revoked key","value":{"error":"Invalid API key","code":"invalid_key"}},"expired":{"summary":"Key past its expiry","value":{"error":"API key expired","code":"key_expired"}},"suspended":{"summary":"Business suspended or owner banned (HTTP 403)","value":{"error":"Account suspended","code":"account_suspended"}}}}}},"ForbiddenScope":{"description":"The key is valid but lacks the scope required for this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Insufficient permissions","code":"forbidden","required":"products:read"}}}},"ForbiddenOrPlanLimit":{"description":"Either the key lacks the required scope (`forbidden`) or the business has hit its plan limit for this resource (`plan_limit_exceeded`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"forbidden":{"summary":"Missing scope","value":{"error":"Insufficient permissions","code":"forbidden","required":"products:write"}},"plan_limit":{"summary":"Plan limit reached","value":{"error":"Product limit reached for your plan. Upgrade to add more.","code":"plan_limit_exceeded"}}}}}},"NotFound":{"description":"No resource with that id exists for this business.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Product not found","code":"not_found"}}}},"ValidationError":{"description":"The request body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"name_required":{"summary":"Missing name","value":{"error":"Name is required","code":"validation_error"}},"price_not_integer":{"summary":"Decimal price","value":{"error":"Price must be an integer (cents). Use 1000 for $10.00, not 10.00.","code":"validation_error"}}}}}},"RateLimited":{"description":"Rate limit exceeded — 30 requests per minute, per API key.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Rate limit exceeded — 30 requests per minute per API key.","code":"rate_limited"}}}}},"schemas":{"Error":{"type":"object","description":"The standard error envelope returned by every `/api/v1/*` error response.","required":["error","code"],"properties":{"error":{"type":"string","description":"Human-readable message. Safe to log; never contains stack traces.","example":"Insufficient permissions"},"code":{"type":"string","description":"Stable, machine-readable error code. Branch on this, not on `error`.","enum":["auth_required","invalid_key","key_expired","account_suspended","forbidden","plan_limit_exceeded","not_found","validation_error","rate_limited"],"example":"forbidden"},"required":{"type":"string","description":"Only present on `forbidden` responses: the scope the key is missing.","example":"products:read"},"invalid":{"type":"array","items":{"type":"string"},"description":"Only present on some `validation_error` responses: the offending values."}}},"ListEnvelope":{"type":"object","description":"Pagination wrapper used by all list endpoints. `data` is overridden with the concrete item type per endpoint.","required":["data","page","limit","has_more"],"properties":{"data":{"type":"array","items":{},"description":"The page of results."},"page":{"type":"integer","description":"The 1-based page number that was returned.","example":1},"limit":{"type":"integer","description":"The page size that was applied (1–100).","example":25},"has_more":{"type":"boolean","description":"`true` when the page came back full, implying another page may exist.","example":false}}},"Product":{"type":"object","description":"A product. Monetary fields are integers in minor units (cents). On `GET` endpoints `images`/`variants`/`metadata` are parsed JSON; on `POST`/`PUT` responses they are returned as the raw stored strings.","properties":{"id":{"type":"string","example":"V1StGXR8_Z5jdHi6B-myT"},"business_id":{"type":"string","example":"biz_8KdLmNpQ"},"name":{"type":"string","example":"Pro License — Lifetime"},"slug":{"type":"string","example":"pro-license-lifetime"},"description":{"type":["string","null"],"example":"One-time purchase, lifetime updates."},"price":{"type":"integer","description":"Price in minor units (cents).","example":14900},"compare_at_price":{"type":["integer","null"],"description":"Strikethrough/original price in minor units.","example":19900},"currency":{"type":"string","description":"ISO-4217 code, lowercase.","example":"usd"},"product_type":{"type":"string","description":"`digital` | `physical` | `service` etc.","example":"digital"},"status":{"type":"string","description":"`draft` | `active` | `archived`.","example":"active"},"images":{"description":"Array of image URLs (parsed on GET; raw JSON string on create/update responses).","type":["array","string","null"],"items":{"type":"string"},"example":["https://cdn.sellstein.com/p/pro-license.png"]},"variants":{"description":"Variant structure if any (parsed on GET; raw JSON string on create/update responses).","type":["object","string","null"]},"weight":{"type":["integer","null"],"description":"Weight (grams). Relevant only when `requires_shipping` is 1."},"requires_shipping":{"type":"integer","enum":[0,1],"description":"Boolean as 0/1.","example":0},"inventory_count":{"type":["integer","null"],"description":"Tracked stock; null when not tracked."},"inventory_tracking":{"type":"integer","enum":[0,1],"example":0},"category_id":{"type":["string","null"]},"sort_order":{"type":"integer","example":0},"metadata":{"description":"Arbitrary key/value metadata (parsed on GET; raw JSON string on create/update responses).","type":["object","string","null"],"example":{"sku":"PRO-LT"}},"created_at":{"type":"string","format":"date-time","example":"2026-05-21T14:03:11.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-06-01T09:12:44.000Z"}}},"ProductCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Required.","example":"Pro License — Lifetime"},"slug":{"type":"string","description":"URL slug. Auto-generated from `name` if omitted."},"description":{"type":"string"},"price":{"type":"integer","minimum":0,"default":0,"description":"Minor units (cents). MUST be an integer — `1999`, not `19.99`.","example":14900},"compare_at_price":{"type":"integer","minimum":0,"description":"Minor units. Non-negative integer.","example":19900},"currency":{"type":"string","default":"usd","example":"usd"},"product_type":{"type":"string","default":"digital","example":"digital"},"status":{"type":"string","default":"draft","description":"`draft` | `active` | `archived`.","example":"active"},"images":{"type":"array","items":{"type":"string"},"example":["https://cdn.sellstein.com/p/pro-license.png"]},"variants":{"type":"object","description":"Variant structure (option groups + variant rows)."},"weight":{"type":"integer","description":"Grams."},"requires_shipping":{"type":"integer","enum":[0,1],"default":0},"inventory_count":{"type":"integer"},"inventory_tracking":{"type":"integer","enum":[0,1],"default":0},"category_id":{"type":"string"},"sort_order":{"type":"integer","default":0},"metadata":{"type":"object","example":{"sku":"PRO-LT"}}}},"ProductUpdate":{"type":"object","description":"Partial update — include only the fields to change. Same field semantics as ProductCreate (minor-unit integers; booleans as 0/1).","properties":{"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"price":{"type":"integer","description":"Minor units (cents)."},"compare_at_price":{"type":["integer","null"],"description":"Minor units."},"currency":{"type":"string"},"product_type":{"type":"string"},"status":{"type":"string"},"category_id":{"type":["string","null"]},"weight":{"type":["integer","null"]},"inventory_count":{"type":["integer","null"]},"sort_order":{"type":"integer"},"requires_shipping":{"type":"integer","enum":[0,1]},"inventory_tracking":{"type":"integer","enum":[0,1]},"images":{"type":["array","null"],"items":{"type":"string"}},"variants":{"type":["object","null"]},"metadata":{"type":["object","null"]}}},"DeleteResult":{"type":"object","required":["success","deleted"],"properties":{"success":{"type":"boolean","example":true},"deleted":{"type":"string","description":"The id of the deleted resource.","example":"V1StGXR8_Z5jdHi6B-myT"}}},"Address":{"type":["object","null"],"description":"A shipping or billing address. Shape is flexible; common fields shown.","properties":{"name":{"type":"string","example":"Jane Buyer"},"line1":{"type":"string","example":"123 Main St"},"line2":{"type":["string","null"]},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"postal_code":{"type":"string","example":"10001"},"country":{"type":"string","description":"ISO-3166 alpha-2.","example":"US"}}},"Order":{"type":"object","description":"An order. Monetary fields are integers in minor units. Orders are created by checkout, never via this API — only their status can be updated.","properties":{"id":{"type":"string","example":"ord7Hn2KpQ9rStUvWxYz0"},"business_id":{"type":"string","example":"biz_8KdLmNpQ"},"order_number":{"type":"integer","description":"Per-business sequential, human-facing number.","example":1042},"customer_id":{"type":["string","null"],"example":"cstAb3Cd4Ef5Gh6Ij7Kl8"},"customer_email":{"type":"string","format":"email","example":"buyer@example.com"},"customer_name":{"type":["string","null"],"example":"Jane Buyer"},"customer_first_name":{"type":["string","null"],"example":"Jane"},"customer_last_name":{"type":["string","null"],"example":"Buyer"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"delivered"},"fulfillment_status":{"type":"string","enum":["unfulfilled","partial","fulfilled"],"example":"fulfilled"},"payment_status":{"type":"string","enum":["pending","paid","refunded","failed"],"description":"`paid` is set only by payment webhooks; it cannot be set via the API.","example":"paid"},"subtotal":{"type":"integer","description":"Minor units.","example":14900},"discount_total":{"type":"integer","description":"Minor units.","example":0},"tax_total":{"type":"integer","description":"Minor units.","example":0},"shipping_total":{"type":"integer","description":"Minor units.","example":0},"total":{"type":"integer","description":"Grand total, minor units.","example":14900},"currency":{"type":"string","example":"usd"},"payment_provider":{"type":["string","null"],"description":"`stripe` | `paypal` | `nmi` | `fiserv` etc.","example":"stripe"},"shipping_address":{"$ref":"#/components/schemas/Address"},"billing_address":{"$ref":"#/components/schemas/Address"},"tracking_number":{"type":["string","null"]},"tracking_carrier":{"type":["string","null"]},"notes":{"type":["string","null"]},"source":{"type":["string","null"],"description":"`checkout` | `terminal` | `subscription` | `api`.","example":"checkout"},"created_at":{"type":"string","format":"date-time","example":"2026-06-02T18:24:55.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-06-02T18:25:10.000Z"}}},"OrderItem":{"type":"object","description":"A line item on an order.","properties":{"id":{"type":"string","example":"itm9Lm0NpQ1rStUvWxYz2"},"order_id":{"type":"string","example":"ord7Hn2KpQ9rStUvWxYz0"},"product_id":{"type":["string","null"],"description":"Null if the product was later deleted.","example":"V1StGXR8_Z5jdHi6B-myT"},"product_name":{"type":"string","example":"Pro License — Lifetime"},"variant_info":{"type":["object","null"],"description":"Parsed variant snapshot."},"quantity":{"type":"integer","example":1},"unit_price":{"type":"integer","description":"Minor units.","example":14900},"total":{"type":"integer","description":"Minor units (unit_price × quantity).","example":14900},"source":{"type":"string","description":"`direct` | `upsell` | `order_bump` | `post_purchase`.","example":"direct"},"created_at":{"type":"string","format":"date-time","example":"2026-06-02T18:24:55.000Z"}}},"Customer":{"type":"object","description":"A customer. Email/name/phone are decrypted on read. Monetary fields are integers in minor units.","properties":{"id":{"type":"string","example":"cstAb3Cd4Ef5Gh6Ij7Kl8"},"business_id":{"type":"string","example":"biz_8KdLmNpQ"},"email":{"type":"string","format":"email","example":"jane@example.com"},"name":{"type":["string","null"],"example":"Jane Buyer"},"first_name":{"type":["string","null"],"example":"Jane"},"last_name":{"type":["string","null"],"example":"Buyer"},"is_company":{"type":"integer","enum":[0,1],"example":0},"company_name":{"type":["string","null"]},"phone":{"type":["string","null"],"example":"+12015550123"},"total_orders":{"type":"integer","example":3},"total_spent":{"type":"integer","description":"Lifetime spend in minor units.","example":44700},"first_order_at":{"type":["string","null"],"format":"date-time"},"last_order_at":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"store_credit_balance":{"type":"integer","description":"Store credit in minor units.","example":0},"created_at":{"type":"string","format":"date-time","example":"2026-04-10T11:00:00.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-06-02T18:25:10.000Z"}}},"RecentOrder":{"type":"object","description":"Compact order summary embedded in a customer's `recent_orders`.","properties":{"id":{"type":"string","example":"ord7Hn2KpQ9rStUvWxYz0"},"order_number":{"type":"integer","example":1042},"status":{"type":"string","example":"delivered"},"total":{"type":"integer","description":"Minor units.","example":14900},"currency":{"type":"string","example":"usd"},"created_at":{"type":"string","format":"date-time","example":"2026-06-02T18:24:55.000Z"}}},"Discount":{"type":"object","description":"A discount code (read-only via this API).","properties":{"id":{"type":"string","example":"dscMn5Op6Qr7St8Uv9Wx0"},"business_id":{"type":"string","example":"biz_8KdLmNpQ"},"code":{"type":"string","example":"LAUNCH10"},"type":{"type":"string","enum":["percentage","fixed"],"example":"percentage"},"value":{"type":"integer","description":"For `percentage`: whole-number percent (10 = 10%). For `fixed`: amount in minor units in `currency`.","example":10},"currency":{"type":"string","description":"Applies to `fixed` codes; ignored for `percentage`.","example":"usd"},"product_id":{"type":["string","null"],"description":"Single-product target when `applies_to` = `product`."},"applies_to":{"type":["string","null"],"description":"`all` | `product` | `products`.","example":"all"},"min_order_amount":{"type":["integer","null"],"description":"Minimum order subtotal (minor units) for the code to apply."},"max_uses":{"type":["integer","null"],"description":"Redemption cap; null = unlimited.","example":100},"used_count":{"type":"integer","example":12},"expires_at":{"type":["string","null"],"format":"date-time","example":"2026-07-31T23:59:59.000Z"},"active":{"type":"integer","enum":[0,1],"example":1},"created_at":{"type":"string","format":"date-time","example":"2026-05-01T08:00:00.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-05-01T08:00:00.000Z"}}},"AnalyticsSummary":{"type":"object","description":"Aggregate store metrics. `total_revenue` is paid-orders-only, in minor units.","properties":{"total_orders":{"type":"integer","description":"All orders regardless of payment status.","example":1042},"paid_orders":{"type":"integer","description":"Orders with `payment_status = 'paid'`.","example":987},"total_revenue":{"type":"integer","description":"Sum of `total` over paid orders, minor units.","example":14702300},"total_customers":{"type":"integer","example":612},"total_products":{"type":"integer","example":24},"active_products":{"type":"integer","description":"Products with status `active`.","example":19}}},"OrderStatusUpdate":{"type":"object","description":"Fields that may be updated on an order. Include only what you want to change.","properties":{"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"]},"fulfillment_status":{"type":"string","enum":["unfulfilled","partial","fulfilled"]},"payment_status":{"type":"string","enum":["pending","refunded","failed"],"description":"`paid` is intentionally NOT accepted — it is set only by verified payment webhooks."},"notes":{"type":"string"}}}}}}