openapi: 3.0.3 info: title: 'CartGenie Public API' description: "This API is served over HTTPS and returns JSON. Every request needs an `Authorization: Bearer ` header.\n\n## Keep the token on your server\n\nA token is scoped to the whole store, not to one shopper or one record. Anything its scopes allow, it allows across every order, product and customer the store has. Treat it as a server-side credential: never ship it to a browser, a mobile app or any other client you do not control.\n\nThis matters most for shopper-facing pages such as order tracking. Call this API from your own backend, verify there that the requester owns the record, and return only that record to the page.\n\n## Pagination\n\nList endpoints are cursor-paginated. Pass `limit` (1–250, default 50; `GET /products` allows at most 50, because each product includes all of its settings) and read `meta.next_cursor` from the response; request the next page by sending that value back as `cursor`. When `meta.has_more` is `false` you have reached the end. Cursors are opaque — do not construct or modify them. Send back only the cursor the same list handed out: a cursor this list cannot read answers `422`, and one from another list that it can read returns the wrong page.\n\n## Keeping data in sync\n\n`products`, `variants`, `orders` and `customers` accept `updated_since`, an ISO-8601 date and time with an offset (`2026-08-01T00:00:00Z` or `2026-08-01T03:00:00+03:00`; encode `+` as `%2B` in a query string). Combined with cursor pagination this gives you an incremental feed of everything that changed since your last poll.\n\nThe product feed also reports removals, and `deleted_at` is the signal: drop any record that carries one, whatever its `status`. Archiving a product in the dashboard unpublishes it, so it arrives here with `deleted_at` set and belongs out of your copy too — a shopper cannot buy it. A product removed permanently arrives collapsed to `\"status\": \"deleted\"` and six fields.\n\nWebhooks and this feed cover different ground. After a missed delivery the incremental feed is the first place to look, and for most changes it returns the record. It is not a complete substitute: some dashboard actions, and some values that are derived rather than stored, raise an event without moving the timestamp the feed filters on, so a missed delivery can fail to resurface. Reconcile against a full listing on a schedule rather than treating `updated_since` as complete.\n\nA published bundle variant's stock is one of those derived values: it is computed from its components, so a sale of a component changes it without moving the bundle's `updated_at`.\n\nCustomers (`GET /customers?updated_since=`), discounts (`GET /discounts`) and categories (`GET /categories`) can be reconciled by listing them. The events for subscriptions, subscription charges and abandoned carts have no endpoint behind them, so no polling reconciles one you never received and the loss is permanent. Those are the deliveries to alert on.\n\nDeliveries are retried on failure, so the same event can reach you more than once. The envelope carries no event or delivery id, so make your receiver idempotent on the payload itself. What identifies a record differs by family: a product payload carries `id`; an order payload `name` and `guid`; a customer payload `customer_email`; a category payload `slug`; a subscription or subscription-charge payload `name` together with `order_id`; an abandoned-cart payload `guid`; and a discount payload `name`, since its `code` is `null` on an automatic discount. An `inventory_updated` payload carries no identifier at all — it names the variant by `sku` and `product_name`, and a SKU is not unique within a store — so treat one as a signal to re-read `GET /variants?sku=` rather than a value to apply directly.\n\nAn event whose retries are all exhausted is dropped, and nothing here reports that: there is no delivery-log endpoint, and a webhook's `last_dispatched_at` records the moment CartGenie queued the delivery, not that you received it. Alert on missing deliveries from your own side.\n\n## Rate limits\n\n120 requests per minute and 4 per second, counted per token. `X-RateLimit-Limit` and `X-RateLimit-Remaining` describe whichever of the two has fewer requests left, which between bursts is the per-second limit (`4`). Exceeding either limit returns `429` with a `Retry-After` header; after a burst over the per-second limit, wait one second before retrying, even when `Retry-After` is `0`.\n\n## Errors\n\nFailures return a JSON body with a `message` field, whatever the request's `Accept` header. `400` means the body is not valid JSON. `401` means the token is missing or invalid, `403` means the token or its owner lacks the required scope or permission, `404` means the record does not exist, the store is archived, or the Public API is not enabled for the store, `405` means the path exists but does not take that method, `422` means validation failed (with an `errors` object), and `409` means the request conflicts with the current state — a stale `expected_stock`, or an order status that does not allow the action. `424` means a service the request depends on could not complete it: Webflow rejected the product or category, refused the store's connection or could not list a field's items, or the payment gateway turned a refund down or left its outcome unknown. The `message` says which. `503` with `Retry-After` means that service is briefly unavailable or rate limiting; retry after the given delay.\n\nThree causes share the `404`, and the `message` tells them apart. A record that does not exist, or belongs to another store, carries `Resource not found.` as its `message`, as does an id that is not a number, even when the token is invalid. An empty `message` means the Public API is not enabled for the store; every endpoint answers that way, including `GET /store`, so it is the first thing to check when a brand-new token gets `404` everywhere. An archived store answers `404` on every endpoint too, with `This store is archived.` as the `message`.\n\nRequests are validated strictly: any parameter that an endpoint does not define is rejected with `422` and `The field is not supported.` rather than ignored. Send only the documented fields — echoing an object back with extra keys will fail. A number may also be sent as a numeric string (`\"2500\"`). A `PATCH` or `PUT` that sends no fields answers `422`. If the endpoint has a required field, the error names that field; otherwise the message is `At least one supported field is required.`\n\nOrder amounts are in the smallest unit of the order's `currency_code`; the `formatted_*` fields use the store's current currency format." version: 1.0.0 servers: - url: 'https://api.cartgenie.com' tags: - name: Store description: '' - name: Products description: '' - name: Variants description: '' - name: Orders description: '' - name: Webhooks description: '' - name: Categories description: '' - name: Customers description: '' - name: 'Custom fields' description: '' - name: Discounts description: '' components: securitySchemes: default: type: http scheme: bearer description: "Tokens are created in the CartGenie dashboard under **Settings → Public API** by a team member with the *Manage store settings* permission.\n\nEach token carries a fixed set of scopes and inherits the permissions of the member who created it, so a request succeeds only when the token scope **and** that member's store role both allow it. Revoking the token, or removing the member from the store, immediately ends access.\n\nThe dashboard picks a token's scopes the way it sets member permissions: an access level per area, never above the creator's own. *View Only* grants the area's read scopes, *Full Access* adds its write scopes:\n\n- **Orders** — `read_orders`; full access adds `write_orders`, `write_refunds`\n- **Products** — `read_products`, `read_categories`; full access adds `write_products`, `write_inventory`, `write_categories`\n- **Discounts** — `read_discounts`; full access adds `write_discounts`\n- **Subscriptions** — `read_subscriptions`\n- **Customers** — `read_customers`; full access adds `write_customers`\n- **Settings** — `read_store`, `read_webhooks`; full access adds `write_webhooks`\n\nThe Public API is enabled per store. Until it is switched on for a store, every endpoint answers `404`." security: - default: [] paths: /public/v1/store: get: summary: 'Get the store' operationId: getTheStore description: "Returns the store the token belongs to. Useful as a connection check: a\n`200` here means the token is valid, the Public API is enabled for the\nstore, and the token's owner still has access to it.\n\nA `404` with an empty `message` has one cause here: the Public API is not\nenabled for the store. Check that before suspecting the token. An archived store answers `404` as well, carrying\n`This store is archived.` as the `message`.\n\n`tax_classes` lists the store's own tax classes; their `id` is what `PUT /products/{id}/tax` takes as\n`tax_class_id` with `tax_class: custom`. `domain` is `null` for a store that has no domain yet.\n\nRequires the `read_store` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: name: 'Example Store' domain: 'https://example.webflow.io' currency: usd timezone: UTC tax_classes: - id: 5 name: 'Reduced rate' created_at: '2025-11-02T08:31:00.000000Z' properties: name: type: string example: 'Example Store' domain: type: string example: 'https://example.webflow.io' currency: type: string example: usd timezone: type: string example: UTC tax_classes: type: array example: - id: 5 name: 'Reduced rate' items: type: object properties: id: type: integer example: 5 name: type: string example: 'Reduced rate' created_at: type: string example: '2025-11-02T08:31:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_store scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_store scope required for this endpoint.' 404: description: '' content: application/json: schema: oneOf: - description: 'Public API is not enabled for this store' type: object example: message: '' properties: message: type: string example: '' - description: 'Store is archived' type: object example: message: 'This store is archived.' properties: message: type: string example: 'This store is archived.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Store /public/v1/tax-codes: get: summary: 'List product tax codes' operationId: listProductTaxCodes description: "The product tax codes of the store's tax provider (TaxJar), which\n`PUT /products/{id}/tax` takes as `tax_code_id`. `default_tax_code_id` is\nthe code used for a product that has none of its own. For a store without a\ntax provider `provider` and `default_tax_code_id` are `null` and `data` is\nempty.\n\nRequires the `read_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: provider: taxjar default_tax_code_id: null data: - id: 41 code: '20010' name: Clothing description: 'All human wearing apparel suitable for general use' properties: provider: type: string example: taxjar default_tax_code_id: type: string example: null nullable: true data: type: array example: - id: 41 code: '20010' name: Clothing description: 'All human wearing apparel suitable for general use' items: type: object properties: id: type: integer example: 41 code: type: string example: '20010' name: type: string example: Clothing description: type: string example: 'All human wearing apparel suitable for general use' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products /public/v1/products: get: summary: 'List products' operationId: listProducts description: "Returns the store's products, oldest update first. Pass `updated_since` to\nreceive an incremental feed: the result then also carries the products the\nstore has removed, so a mirrored catalog can drop them.\n\n`deleted_at` is the removal signal — drop any record that carries one,\nwhatever its `status`. Removal reaches the feed in two shapes. A product\narchived in the dashboard keeps the full product shape and its own status. A\nproduct removed permanently collapses to `\"status\": \"deleted\"` and carries\nonly `id`, `name`, `slug`, `status`, `deleted_at` and `updated_at` — no\n`price`, `stock`, `variants`, `images`, `url` or `created_at`. Read\n`deleted_at` and `status` before any other field.\n\nArchiving is a removal here by design: it unpublishes the product, so a\nshopper cannot buy it and it belongs out of any catalog you mirror from\nthis feed. Restoring the product in the dashboard returns it to a later page\nwith `deleted_at` back to `null`, carrying whatever status the restoring\naction set: un-archiving returns it as `draft`, publishing straight out of\nthe archive returns it as `published`. It is buyable again only once it is\npublished.\n\nReconcile against a full listing on a schedule: a permanent removal is not\nguaranteed to reach the feed.\n\n`stock`, `available_stock` and `track_inventory` are product-level roll-ups\nover the variants that carry an option combination. A product with option\nsets can also hold a variant that carries none of them (`options: []`); it is\nlisted in `variants` and accepts `PUT /variants/{id}/inventory`, but\ncontributes nothing to these three fields, so the totals need not match and\n`track_inventory` can differ from that variant's own. Treat the product-level\nfigures as the sellable quantity rather than deriving one from the `variants`\narray.\n\nA change this API makes to one of the product's variants moves the product's\n`updated_at`, so the product comes back in the `updated_since` feed. Stock\nchanges do not always reach it — orders selling stock down never do — so\nfollow stock with the `inventory_updated` webhook.\n\nEach product carries the fields and blocks described under `GET /products/{id}`.\n\nRequires the `read_products` token scope." parameters: - in: query name: limit description: 'Results per page, 1–50.' example: 50 required: false schema: type: integer description: 'Results per page, 1–50.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null - in: query name: search description: 'Matches against product name and slug.' example: tee required: false schema: type: string description: 'Matches against product name and slug.' example: tee - in: query name: slug description: 'The exact slug of one product.' example: classic-tee required: false schema: type: string description: 'The exact slug of one product.' example: classic-tee - in: query name: updated_since description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`). Returns products changed or deleted since then.' example: '2026-08-01T00:00:00Z' required: false schema: type: string description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`). Returns products changed or deleted since then.' example: '2026-08-01T00:00:00Z' responses: 200: description: '' content: application/json: schema: oneOf: - description: 'Catalog page' type: object example: data: - id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' meta: per_page: 50 has_more: true next_cursor: eyJpZCI6MzY0fQ properties: data: type: array example: - id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: 12: Cotton 13: 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - { id: 88, value: M, color: null } - { id: 89, value: L, color: null } items: type: object properties: { id: { type: integer, example: 88 }, value: { type: string, example: M }, color: { type: string, example: null, nullable: true } } bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: { type: integer, example: 902 } url: { type: string, example: 'https://cdn.example.com/tee-back.jpg' } alt_text: { type: string, example: null, nullable: true } url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - { option_id: 31, option: Size, value_id: 88, value: M } items: type: object properties: { option_id: { type: integer, example: 31 }, option: { type: string, example: Size }, value_id: { type: integer, example: 88 }, value: { type: string, example: M } } subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: { type: object, properties: { id: { type: integer, example: 903 }, url: { type: string, example: 'https://cdn.example.com/tee.jpg' }, alt_text: { type: string, example: 'Black cotton tee' } } } extra: { type: array, example: [] } hide_main_image: { type: boolean, example: false } hide_extra_images: { type: boolean, example: false } stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: { type: integer, example: 200 } length: { type: integer, example: 3000 } width: { type: integer, example: 2000 } weight: { type: integer, example: 18000 } created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: true next_cursor: type: string example: eyJpZCI6MzY0fQ - description: 'Incremental feed carrying both removal shapes' type: object example: data: - id: 351 name: 'Summer Cap' slug: summer-cap status: deleted deleted_at: '2026-08-03T14:22:09.000000Z' updated_at: '2026-08-03T14:22:09.000000Z' - id: 358 name: 'Winter Scarf' slug: winter-scarf status: archived published: false price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton scarf.

' meta_description: 'Soft cotton scarf in grey.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-SCARF-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2288 options: [] bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6117.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/scarf.jpg' main_image_large: 'https://cdn.example.com/scarf-large.jpg' main: id: 901 url: 'https://cdn.example.com/scarf.jpg' alt_text: 'Grey cotton scarf' extra: - id: 902 url: 'https://cdn.example.com/scarf-back.jpg' alt_text: null url: 'https://store.example.com/product/winter-scarf' variants: - id: 2288 product_id: 358 sku: SCARF-GRY title: SCARF-GRY published: false price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: [] subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/scarf.jpg' alt_text: 'Grey cotton scarf' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-02-02T08:12:00.000000Z' updated_at: '2026-08-04T09:15:44.000000Z' created_at: '2026-02-02T08:12:00.000000Z' deleted_at: '2026-08-04T09:15:44.000000Z' updated_at: '2026-08-04T09:15:44.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 351 name: 'Summer Cap' slug: summer-cap status: deleted deleted_at: '2026-08-03T14:22:09.000000Z' updated_at: '2026-08-03T14:22:09.000000Z' - id: 358 name: 'Winter Scarf' slug: winter-scarf status: archived published: false price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton scarf.

' meta_description: 'Soft cotton scarf in grey.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-SCARF-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2288 options: [] bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6117.10' country_of_origin: pt custom_fields: 12: Cotton 13: 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/scarf.jpg' main_image_large: 'https://cdn.example.com/scarf-large.jpg' main: id: 901 url: 'https://cdn.example.com/scarf.jpg' alt_text: 'Grey cotton scarf' extra: - id: 902 url: 'https://cdn.example.com/scarf-back.jpg' alt_text: null url: 'https://store.example.com/product/winter-scarf' variants: - id: 2288 product_id: 358 sku: SCARF-GRY title: SCARF-GRY published: false price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: [] subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/scarf.jpg' alt_text: 'Grey cotton scarf' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-02-02T08:12:00.000000Z' updated_at: '2026-08-04T09:15:44.000000Z' created_at: '2026-02-02T08:12:00.000000Z' deleted_at: '2026-08-04T09:15:44.000000Z' updated_at: '2026-08-04T09:15:44.000000Z' items: type: object properties: id: type: integer example: 351 name: type: string example: 'Summer Cap' slug: type: string example: summer-cap status: type: string example: deleted deleted_at: type: string example: '2026-08-03T14:22:09.000000Z' updated_at: type: string example: '2026-08-03T14:22:09.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products post: summary: 'Create a product' operationId: createAProduct description: "Creates a draft product with one variant from the fields a product needs up\nfront: its name and price, plus the optional details `PATCH /products/{id}`\nalso takes. Everything else is set afterwards with its own endpoint —\ncategories, tax class, shipping, then the variant's SKU, weight and\ndimensions (`PATCH /variants/{id}`) and stock\n(`PUT /variants/{id}/inventory`) — and the product goes live with\n`PUT /products/{id}/status`. Until then it exists only in CartGenie, so\ncreating it never waits on Webflow.\n\n`price` is in the store currency's smallest unit. Without `slug` one is made\nfrom the name and numbered past the store's existing slugs\n(`classic-tee-2`). A new product uses the built-in `default` tax class and\nthe `physical` type unless `product_type` says otherwise.\n\nFires the `new_product` webhook.\n\nRequires the `write_products` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 366 name: 'Classic Tee' slug: classic-tee status: draft published: false price: 2500 formatted_price: $25.00 stock: 0 available_stock: 0 track_inventory: false description: '

Soft cotton tee.

' meta_description: 'A soft cotton tee.' product_type: physical categories: category_ids: [] primary_category_id: null tax: tax_class: default tax_class_id: null tax_code_id: null purchase_limits: min_quantity_per_order: null max_quantity_per_order: null pre_order: pre_order: false estimated_shipping_date: null feed: brand: null condition: new mpn: null gtin: null google_product_category_id: null include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: [] download: null default_variant_id: 2352 options: [] bundle: null shipping: requires_shipping: false auto_fulfill_order: false hs_code: null country_of_origin: null custom_fields: '12': Cotton '13': null images: main_image: '' main_image_large: '' main: null extra: [] url: 'https://store.example.com/product/classic-tee' variants: - id: 2352 product_id: 366 sku: null title: null published: false price: 2500 formatted_price: $25.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 0 reserved_stock: 0 available_stock: 0 track_inventory: false requires_shipping: false dimensions: height: null length: null width: null weight: null created_at: '2026-10-06T09:00:00.000000Z' updated_at: '2026-10-06T09:00:00.000000Z' created_at: '2026-10-06T09:00:00.000000Z' deleted_at: null updated_at: '2026-10-06T09:00:00.000000Z' properties: id: type: integer example: 366 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: draft published: type: boolean example: false price: type: integer example: 2500 formatted_price: type: string example: $25.00 stock: type: integer example: 0 available_stock: type: integer example: 0 track_inventory: type: boolean example: false description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'A soft cotton tee.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: [] primary_category_id: type: string example: null nullable: true tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: string example: null nullable: true purchase_limits: type: object properties: min_quantity_per_order: type: string example: null nullable: true max_quantity_per_order: type: string example: null nullable: true pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: null nullable: true condition: type: string example: new mpn: type: string example: null nullable: true gtin: type: string example: null nullable: true google_product_category_id: type: string example: null nullable: true include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: [] download: type: string example: null nullable: true default_variant_id: type: integer example: 2352 options: type: array example: [] bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: false auto_fulfill_order: type: boolean example: false hs_code: type: string example: null nullable: true country_of_origin: type: string example: null nullable: true custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: null nullable: true images: type: object properties: main_image: type: string example: '' main_image_large: type: string example: '' main: type: string example: null nullable: true extra: type: array example: [] url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2352 product_id: 366 sku: null title: null published: false price: 2500 formatted_price: $25.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 0 reserved_stock: 0 available_stock: 0 track_inventory: false requires_shipping: false dimensions: height: null length: null width: null weight: null created_at: '2026-10-06T09:00:00.000000Z' updated_at: '2026-10-06T09:00:00.000000Z' items: type: object properties: id: type: integer example: 2352 product_id: type: integer example: 366 sku: type: string example: null nullable: true title: type: string example: null nullable: true published: type: boolean example: false price: type: integer example: 2500 formatted_price: type: string example: $25.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: [] subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: string example: null nullable: true extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 0 reserved_stock: type: integer example: 0 available_stock: type: integer example: 0 track_inventory: type: boolean example: false requires_shipping: type: boolean example: false dimensions: type: object properties: height: type: string example: null nullable: true length: type: string example: null nullable: true width: type: string example: null nullable: true weight: type: string example: null nullable: true created_at: type: string example: '2026-10-06T09:00:00.000000Z' updated_at: type: string example: '2026-10-06T09:00:00.000000Z' created_at: type: string example: '2026-10-06T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-10-06T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 422: description: 'Slug taken' content: application/json: schema: type: object example: message: 'The slug has already been taken.' errors: slug: - 'The slug has already been taken.' properties: message: type: string example: 'The slug has already been taken.' errors: type: object properties: slug: type: array example: - 'The slug has already been taken.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: custom_fields: type: object description: 'Values by custom field id from `GET /products/custom-fields`; every `required` field needs one.' example: 12: Cotton properties: {} name: type: string description: '' example: 'Classic Tee' slug: type: string description: 'Unique in the store.' example: classic-tee description: type: string description: 'HTML allowed, as in the product editor.' example: '

Soft cotton tee.

' nullable: true meta_description: type: string description: '' example: 'A soft cotton tee.' nullable: true product_type: type: string description: '`physical` (default), `digital`, `service` or `advanced`.' example: physical price: type: integer description: 'In the smallest currency unit.' example: 2500 required: - name - price '/public/v1/products/{id}': get: summary: 'Get a product' operationId: getAProduct description: "Includes the product's variants.\n\n`stock`, `available_stock` and `track_inventory` are product-level roll-ups over the\nvariants that carry an option combination, so they need not equal the sum of the\n`variants` array and `track_inventory` can differ from an individual variant's own.\nSee the list endpoint for the full explanation.\n\nA product carries `description`, `meta_description`, `product_type`,\n`custom_fields` and one block per settings endpoint — `categories`, `tax`,\n`shipping`, and `purchase_limits`, `pre_order`, `feed` and\n`personalization_fields` where the store has that feature turned on. Each\nblock has the shape its endpoint accepts, so you can edit a block and send\nit back; `personalization_fields` is a list, sent back as\n`{\"personalization_fields\": [...]}`. A variant's `compare_at_price` and\n`formatted_compare_at_price` are null when not set.\n\n`published` says whether the product is on sale on the storefront. It can\ndiffer from `status`: a product on sale can read `queued`, or `sync_error`\nafter Webflow refused a change, and stays on sale until it is moved to\n`draft` or archived.\n\nRequires the `read_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products patch: summary: 'Update a product' operationId: updateAProduct description: "Changes the product's own details. Only the fields you send change. Other\nparts of the product have their own endpoints: status\n(`PUT /products/{id}/status`), categories, tax class, shipping, purchase\nlimits, pre-order, feed details and personalization fields;\nprices, SKUs, weight and dimensions live on the variants\n(`PATCH /variants/{id}`).\n\n`slug` is normalized the way the product editor does it (`Classic Tee!`\nbecomes `classic-tee`) and changes the product's page address on the\nsite. `product_type` is `physical`, `digital`, `service` or `advanced`.\n\nSaving works like the product editor's Save: a draft or queued product\nonly changes in CartGenie, and a published product is republished with the\nchange, Webflow included, before the response. When Webflow refuses the\nproduct nothing is saved (424); when Webflow is rate limiting the site\nnothing is saved and the call answers 503 with `Retry-After`. When the\nchange would leave a published product unable to be published (no shipping\nzones for a shippable product, no Webflow products collection), the call\nanswers 422 and nothing is saved.\n\nFires the `product_updated` webhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Published product cannot be republished' content: application/json: schema: type: object example: message: 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' errors: product: - 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' properties: message: type: string example: 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' errors: type: object properties: product: type: array example: - 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: custom_fields: type: object description: 'Values by custom field id from `GET /products/custom-fields`; only the fields sent change, `null` clears one.' example: 12: Cotton properties: {} name: type: string description: '' example: 'Classic Tee' slug: type: string description: 'Unique in the store.' example: classic-tee description: type: string description: 'HTML allowed, as in the product editor.' example: '

Soft cotton tee.

' nullable: true meta_description: type: string description: '' example: 'Soft cotton tee in five colors.' nullable: true product_type: type: string description: '`physical`, `digital`, `service` or `advanced`.' example: physical parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/status': put: summary: "Set a product's status" operationId: setAProductsStatus description: "Works like the product editor's save buttons: `draft` takes the product\noff the live site, `queued` stages it for the next Webflow site publish,\nand `published` publishes it. Stores without Webflow treat `queued` as\n`published`. This is the one endpoint that sends a draft or queued product to\nWebflow; the other product endpoints only change it in CartGenie until then.\n\nThe Webflow item is written before the response. When Webflow refuses the\nproduct, the call answers 424 and the requested status is not applied. A\nproduct that was not published is then marked `sync_error`, as in the\neditor, with no webhook, and stays there until Webflow accepts a later\nstatus change. When Webflow is rate limiting the site, nothing changes and\nthe call answers 503 with `Retry-After`.\n\nFires the `product_updated` webhook when the status changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Product cannot be published' content: application/json: schema: type: object example: message: 'Product contains shippable variants but store has no shipping zones configured.' errors: status: - 'Product contains shippable variants but store has no shipping zones configured.' properties: message: type: string example: 'Product contains shippable variants but store has no shipping zones configured.' errors: type: object properties: status: type: array example: - 'Product contains shippable variants but store has no shipping zones configured.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: status: type: string description: '`draft`, `queued` or `published`.' example: published required: - status parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/categories': put: summary: "Set a product's categories" operationId: setAProductsCategories description: "`category_ids` replaces the whole list and reads back sorted by id; send\n`[]` to remove the product from every category. `primary_category_id` is\nthe category that product feeds use and must be one of `category_ids`;\nwithout it the current primary category stays while it is still in the\nlist, otherwise the first category sent becomes primary, as in the product\neditor.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Primary category not in the list' content: application/json: schema: type: object example: message: 'The primary category must be one of category_ids.' errors: primary_category_id: - 'The primary category must be one of category_ids.' properties: message: type: string example: 'The primary category must be one of category_ids.' errors: type: object properties: primary_category_id: type: array example: - 'The primary category must be one of category_ids.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: category_ids: type: array description: 'Ids from `GET /categories`.' example: - 7 - 9 items: type: integer primary_category_id: type: integer description: 'One of `category_ids`.' example: 7 nullable: true required: - category_ids parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/tax': put: summary: "Set a product's tax class and tax code" operationId: setAProductsTaxClassAndTaxCode description: "`tax_class` is `default`, `non_taxable` or `custom` with the\n`tax_class_id` of one of the store's tax classes (`GET /store` lists\nthem). With tax-inclusive pricing, each variant keeps its price and the tax\nincluded in it follows the new class, as in the product editor.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Tax class of another store' content: application/json: schema: type: object example: message: 'The selected tax class id is invalid.' errors: tax_class_id: - 'The selected tax class id is invalid.' properties: message: type: string example: 'The selected tax class id is invalid.' errors: type: object properties: tax_class_id: type: array example: - 'The selected tax class id is invalid.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: tax_class: type: string description: '`default`, `non_taxable` or `custom`.' example: custom tax_class_id: type: integer description: 'Required with `tax_class: custom`; with a built-in class only `null`, as the product reads back.' example: 5 nullable: true tax_code_id: type: integer description: "The tax provider's product tax code, from `GET /tax-codes`; `null` falls back to the provider's default code, leaving it out keeps the current one." example: 41 nullable: true required: - tax_class parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/shipping': put: summary: "Set a product's shipping details" operationId: setAProductsShippingDetails description: "Only the fields you send change. `requires_shipping` applies to every\nvariant, as in the product editor. `auto_fulfill_order` marks orders\nfulfilled right after purchase and only fits a product that does not\nship: turning shipping on for such a product needs\n`auto_fulfill_order: false` in the same call. `hs_code` and\n`country_of_origin` (a two-letter code) are the customs details for\ninternational orders. A bundle takes all of these from its components and\nrefuses them.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published — for example when shipping\nis turned on and the store has no shipping zones). Fires the\n`product_updated` webhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Automatic fulfillment on a product that ships' content: application/json: schema: type: object example: message: 'A product that requires shipping is fulfilled when it ships, not automatically. Send auto_fulfill_order false with requires_shipping true.' errors: auto_fulfill_order: - 'A product that requires shipping is fulfilled when it ships, not automatically. Send auto_fulfill_order false with requires_shipping true.' properties: message: type: string example: 'A product that requires shipping is fulfilled when it ships, not automatically. Send auto_fulfill_order false with requires_shipping true.' errors: type: object properties: auto_fulfill_order: type: array example: - 'A product that requires shipping is fulfilled when it ships, not automatically. Send auto_fulfill_order false with requires_shipping true.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: requires_shipping: type: boolean description: '' example: true auto_fulfill_order: type: boolean description: '' example: false hs_code: type: string description: 'Send null to clear it.' example: '6109.10' nullable: true country_of_origin: type: string description: 'Send null to clear it.' example: pt nullable: true parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/purchase-limits': put: summary: "Set a product's purchase limits" operationId: setAProductsPurchaseLimits description: "The smallest and largest quantity of the product one order may hold. Only\nthe fields you send change; `null` removes a limit, and both `null` turn\nlimits off. Sending a maximum to a product without limits sets the minimum\nto 1. A new minimum above 1 may not exceed the stock of a product that\ntracks inventory. A store without purchase limits enabled answers 422.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Minimum above the stock' content: application/json: schema: type: object example: message: 'The minimum quantity per order cannot exceed the 3 currently in stock.' errors: min_quantity_per_order: - 'The minimum quantity per order cannot exceed the 3 currently in stock.' properties: message: type: string example: 'The minimum quantity per order cannot exceed the 3 currently in stock.' errors: type: object properties: min_quantity_per_order: type: array example: - 'The minimum quantity per order cannot exceed the 3 currently in stock.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: min_quantity_per_order: type: integer description: '' example: 2 nullable: true max_quantity_per_order: type: integer description: '' example: 10 nullable: true parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/pre-order': put: summary: "Set a product's pre-order settings" operationId: setAProductsPreOrderSettings description: "`pre_order: true` sells the product ahead of stock: orders placed meanwhile\nare marked as pre-orders in the cart, checkout and order confirmation.\n`estimated_shipping_date` is free text shown to shoppers (\"Mid 2026\",\n\"Jan 15, 2026\") and exists only while the product is a pre-order, so turning\npre-order off clears it. Only the fields you send change. A store without\npre-orders enabled answers 422.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it or its\npre-order fields cannot be created, 503 with `Retry-After` when Webflow is\nrate limiting the site, 422 when the change would leave the product unable\nto be published). Fires the `product_updated` webhook when something\nchanged.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Date without pre-order' content: application/json: schema: type: object example: message: 'An estimated shipping date applies only to a pre-order. Send pre_order true with it.' errors: estimated_shipping_date: - 'An estimated shipping date applies only to a pre-order. Send pre_order true with it.' properties: message: type: string example: 'An estimated shipping date applies only to a pre-order. Send pre_order true with it.' errors: type: object properties: estimated_shipping_date: type: array example: - 'An estimated shipping date applies only to a pre-order. Send pre_order true with it.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: pre_order: type: boolean description: '' example: true estimated_shipping_date: type: string description: 'Needs `pre_order` true.' example: 'Mid 2026' nullable: true parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/feed': put: summary: "Set a product's feed details" operationId: setAProductsFeedDetails description: "What product feeds (Google Shopping and others) send for the product. Only\nthe fields you send change. `condition` is `new`, `used` or `refurbished`;\n`gtin` is 8 to 14 digits; `google_product_category_id` is an id from\nGoogle's product taxonomy; `gender` (`male`, `female`, `unisex`) and\n`age_group` (`newborn`, `infant`, `toddler`, `kids`, `adult`) apply to every\nvariant, as in the product editor. The primary category used by feeds is\nset with `PUT /products/{id}/categories`. A store without product feeds enabled\nanswers 422.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Malformed GTIN' content: application/json: schema: type: object example: message: 'The gtin field format is invalid.' errors: gtin: - 'The gtin field format is invalid.' properties: message: type: string example: 'The gtin field format is invalid.' errors: type: object properties: gtin: type: array example: - 'The gtin field format is invalid.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: brand: type: string description: '' example: Northwind nullable: true condition: type: string description: '' example: new mpn: type: string description: '' example: NW-TEE-01 nullable: true gtin: type: string description: '' example: '00012345678905' nullable: true google_product_category_id: type: integer description: '' example: 212 nullable: true include_variant_info_in_title_feed: type: boolean description: '' example: true gender: type: string description: '' example: unisex age_group: type: string description: '' example: adult parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/personalization-fields': put: summary: "Set a product's personalization fields" operationId: setAProductsPersonalizationFields description: "The fields a shopper fills in when adding the product to the cart, such as\nan engraving text. `personalization_fields` replaces the whole list, in\norder; send `[]` to remove them all. Up to 10 fields; names must be unique,\nignoring case. `required` defaults to false. Fields are matched by name, so\nrenaming a field replaces it with a new one. A store without personalization\nfields enabled answers 422.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Duplicate names' content: application/json: schema: type: object example: message: 'Make sure that all personalization field names are unique.' errors: personalization_fields: - 'Make sure that all personalization field names are unique.' properties: message: type: string example: 'Make sure that all personalization field names are unique.' errors: type: object properties: personalization_fields: type: array example: - 'Make sure that all personalization field names are unique.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: personalization_fields: type: array description: '' items: type: object properties: name: type: string description: '' example: Engraving placeholder: type: string description: 'Hint shown inside the empty input.' example: 'Up to 20 letters' nullable: true help: type: string description: 'Help text shown with the field.' example: 'Printed on the back.' nullable: true required: type: boolean description: '' example: false required: - name required: - personalization_fields parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/download': put: summary: "Set a product's digital download" operationId: setAProductsDigitalDownload description: "The file a buyer gets a link to after paying, by name and URL. Every variant\nwithout a file of its own gets it, as the product editor's Digital Download\ndoes; a variant with its own file (`PUT /variants/{id}/download`) keeps it.\nWhere the store does not offer per-variant files, every variant gets it. A bundle is\nrefused: its buyers get the files of its components.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: name: 'Pattern (PDF)' url: 'https://files.example.com/pattern.pdf' default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: object properties: name: type: string example: 'Pattern (PDF)' url: type: string example: 'https://files.example.com/pattern.pdf' default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Not a link' content: application/json: schema: type: object example: message: 'The url field must be a valid URL.' errors: url: - 'The url field must be a valid URL.' properties: message: type: string example: 'The url field must be a valid URL.' errors: type: object properties: url: type: array example: - 'The url field must be a valid URL.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: '' example: 'Pattern (PDF)' url: type: string description: 'An http or https link.' example: 'https://files.example.com/pattern.pdf' required: - name - url delete: summary: "Remove a product's digital download" operationId: removeAProductsDigitalDownload description: "Removes the product's file from every variant that carries it; a variant\nwith a file of its own keeps that one.\n\nWorks like Save in the product editor, with the same responses as\n`PUT /products/{id}/download`. Fires the `product_updated` webhook when\nsomething changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/images': put: summary: "Set a product's images" operationId: setAProductsImages description: "Replaces the main image, the extra images, or both, as the product\neditor's image uploaders do. An image is `{\"id\": …}` to keep one the\nproduct has — as read under `images.main` and `images.extra` — or\n`{\"url\": …}` to add a new one, downloaded from a public HTTPS address (an\nimage of up to 4 MB: JPEG, PNG, BMP, GIF, SVG, WebP or AVIF). Each takes an\n`alt_text`; left out, the image has none. Where the store does not have\nimage alt text turned on, responses leave `alt_text` out and sending it\nreturns 422; existing alt text is kept.\n\n`main` null removes the main image. `extra` is the whole gallery in order,\nup to 25: an extra image left out is deleted. Leave `main` or `extra` out to\nkeep those images as they are. The product's first variant shows the main image, as in the editor.\n\nWorks like Save in the product editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). If the republish fails, no\nimages are removed. Fires the `product_updated` webhook when something\nchanged.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Image could not be downloaded' content: application/json: schema: type: object example: message: 'The file at https://cdn.example.com/tee.jpg could not be downloaded: the server answered 404.' errors: main.url: - 'The file at https://cdn.example.com/tee.jpg could not be downloaded: the server answered 404.' properties: message: type: string example: 'The file at https://cdn.example.com/tee.jpg could not be downloaded: the server answered 404.' errors: type: object properties: main.url: type: array example: - 'The file at https://cdn.example.com/tee.jpg could not be downloaded: the server answered 404.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: main: type: object description: 'The main image, or null to remove it.' properties: id: type: integer description: 'The id of the current main image, to keep it.' example: 901 url: type: string description: 'Required for a new image.' example: 'https://cdn.example.com/tee.jpg' alt_text: type: string description: '' example: 'Black cotton tee' nullable: true nullable: true extra: type: array description: 'The extra images in order.' items: type: object properties: id: type: integer description: 'The id of one of the current extra images, to keep it.' example: 902 url: type: string description: 'Required for a new image.' example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string description: '' example: 'Back of the tee' nullable: true parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/options': post: summary: 'Add a product option' operationId: addAProductOption description: "Adds an option set — up to three per product — and makes a variant for every\nnew combination, as the product editor's options do. Each new variant copies\nthe price, SKU and settings of the existing variant it extends; when there is\nnone, it copies the product's first variant, without the SKU. A product has at\nmost 100 combinations, 200 where the store's plan allows more.\n\n`swatch_type` is `button` (default) or `color`; a color swatch needs a\n`color` (`#rrggbb`) for every value. Image swatches are set in the dashboard.\nWhere the store does not have option swatches turned on, responses leave\n`swatch_type` and `color` out, sending them returns 422, and options are\nsaved as buttons, as in the dashboard.\n\nWorks like Save in the product editor: a published product is republished\nwith its new variants before the response (424 when Webflow refuses it, 503\nwith `Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook.\n\nRequires the `write_products` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Too many combinations' content: application/json: schema: type: object example: message: 'These values make 120 combinations; a product has at most 100.' errors: values: - 'These values make 120 combinations; a product has at most 100.' properties: message: type: string example: 'These values make 120 combinations; a product has at most 100.' errors: type: object properties: values: type: array example: - 'These values make 120 combinations; a product has at most 100.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: "Unique among the product's options regardless of case." example: Size swatch_type: type: string description: '`button` or `color`.' example: button values: type: array description: 'In display order, unique regardless of case.' items: type: object properties: id: type: integer description: 'Leave out: the values of a new option have no ids yet.' example: null nullable: true value: type: string description: '' example: M color: type: string description: 'Required for swatch_type color.' example: null nullable: true required: - value required: - name - values parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/options/{option}': patch: summary: 'Update a product option' operationId: updateAProductOption description: "Renames the option set, changes its swatch type or its values. `values`\nreplaces the list in order: a value sent with its `id` keeps its variants\nwhile its text changes, a value without an `id` is added with new\ncombinations, and a value left out is removed together with its variants.\nLeave `values` out to keep the current values. An option with image swatches\nreads back with `swatch_type: image`; leave `swatch_type` out or send\n`image` to keep them, and each kept value keeps its image.\nThe option as read can be sent back as it is, `id` included.\n\nWorks like Save in the product editor, with the same responses as\n`POST /products/{id}/options`. Fires the `product_updated` webhook when\nsomething changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Option of another product' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Value of another option' content: application/json: schema: type: object example: message: 'The value id must be one of the values of this option.' errors: values.0.id: - 'The value id must be one of the values of this option.' properties: message: type: string example: 'The value id must be one of the values of this option.' errors: type: object properties: values.0.id: type: array example: - 'The value id must be one of the values of this option.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: '' example: Size swatch_type: type: string description: '`button` or `color`; `image` for an option that already has it.' example: button values: type: array description: '' items: type: object properties: id: type: integer description: "A value id from the option's `values`; leave out for a new value." example: 88 nullable: true value: type: string description: '' example: Medium color: type: string description: 'Required for swatch_type color.' example: null nullable: true required: - value id: type: integer description: 'The option id from the path, when sending the option back as read.' example: 31 delete: summary: 'Delete a product option' operationId: deleteAProductOption description: "Deletes an option set and rebuilds the variants from the options left. If\nother options remain and the variants carry more than one of this option's\nvalues, send `keep_value_id` to choose which value's variants to keep, with their prices,\nSKUs and stock; the variants of the other values are deleted, as in the\nproduct editor. Without that choice the call answers 422 listing the values\nto choose from. Every other variant that matches no combination of the remaining\noptions is deleted too, including a variant with no options (`options: []`),\nunless it is the product's default variant.\n\nWorks like Save in the product editor. Fires the `product_updated` webhook.\n\nRequires the `write_products` token scope." parameters: - in: query name: keep_value_id description: 'The value whose variants stay.' example: 88 required: false schema: type: integer description: 'The value whose variants stay.' example: 88 responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Value to keep not chosen' content: application/json: schema: type: object example: message: 'Choose the value whose variants stay, as keep_value_id: 88 (M), 89 (L). The variants of the other values are deleted.' errors: keep_value_id: - 'Choose the value whose variants stay, as keep_value_id: 88 (M), 89 (L). The variants of the other values are deleted.' properties: message: type: string example: 'Choose the value whose variants stay, as keep_value_id: 88 (M), 89 (L). The variants of the other values are deleted.' errors: type: object properties: keep_value_id: type: array example: - 'Choose the value whose variants stay, as keep_value_id: 88 (M), 89 (L). The variants of the other values are deleted.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer - in: path name: option description: "The option id from the product's `options`." example: 31 required: true schema: type: integer '/public/v1/products/{id}/default-variant': put: summary: "Set a product's default variant" operationId: setAProductsDefaultVariant description: "The variant the storefront preselects. `null` removes the choice, as\nunstarring the variant in the product editor does. A disabled variant cannot\nbe the default. Works only where the store has default variants turned on;\notherwise the call returns 422 and products carry no `default_variant_id`.\n\nWorks like Save in the product editor. Fires the `product_updated` webhook\nwhen the default changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 364 name: 'Classic Tee' slug: classic-tee status: published published: true price: 4900 formatted_price: $49.00 stock: 120 available_stock: 118 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2301 options: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/classic-tee' variants: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 364 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee status: type: string example: published published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 stock: type: integer example: 120 available_stock: type: integer example: 118 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2301 options: type: array example: - id: 31 name: Size swatch_type: button values: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 31 name: type: string example: Size swatch_type: type: string example: button values: type: array example: - id: 88 value: M color: null - id: 89 value: L color: null items: type: object properties: id: type: integer example: 88 value: type: string example: M color: type: string example: null nullable: true bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/classic-tee' variants: type: array example: - id: 2301 product_id: 364 sku: TEE-BLK-M title: black-medium published: true price: 4900 formatted_price: $49.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: null images: main: id: 903 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: [] hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-01T11:20:31.000000Z' items: type: object properties: id: type: integer example: 2301 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: black-medium published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: object properties: id: type: integer example: 903 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-01T11:20:31.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Disabled variant' content: application/json: schema: type: object example: message: 'A disabled variant cannot be the default. Enable it first.' errors: variant_id: - 'A disabled variant cannot be the default. Enable it first.' properties: message: type: string example: 'A disabled variant cannot be the default. Enable it first.' errors: type: object properties: variant_id: type: array example: - 'A disabled variant cannot be the default. Enable it first.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: variant_id: type: integer description: "The id of one of the product's variants, or null to remove the default." example: 2302 nullable: true required: - variant_id parameters: - in: path name: id description: 'The product id.' example: 364 required: true schema: type: integer '/public/v1/products/{id}/bundle': put: summary: "Set a bundle's components" operationId: setABundlesComponents description: "Makes the product a bundle of `components` — or, for a bundle, replaces its\ncomponents — as the product editor does. Each component is a variant of\nanother product of the store that is not itself a bundle, is paid once (not\na subscription) and is published, scheduled or queued; a product that is a\ncomponent of a bundle cannot become one. A variant of the bundle that\noverrides a component's quantity in the editor keeps its own quantity while\nthe component stays. A bundle's stock, weight, shipping and customs details\ncome from its components, and it is never fulfilled automatically, so a product\nwith automatic fulfillment must turn it off first.\n\nWorks like Save in the product editor: a published bundle is republished with\nthe change before the response, which needs every component on the live\nsite (424 when Webflow refuses it, 503 with `Retry-After` when Webflow is\nrate limiting the site). Fires the `product_updated` webhook when something\nchanged.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 371 name: 'Starter kit' slug: starter-kit status: published published: true price: 6900 formatted_price: $69.00 stock: 40 available_stock: 40 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2380 options: [] bundle: components: - variant_id: 2301 quantity: 2 - variant_id: 2310 quantity: 1 shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/starter-kit' variants: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 371 name: type: string example: 'Starter kit' slug: type: string example: starter-kit status: type: string example: published published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 stock: type: integer example: 40 available_stock: type: integer example: 40 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2380 options: type: array example: [] bundle: type: object properties: components: type: array example: - variant_id: 2301 quantity: 2 - variant_id: 2310 quantity: 1 items: type: object properties: variant_id: type: integer example: 2301 quantity: type: integer example: 2 shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/starter-kit' variants: type: array example: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 2380 product_id: type: integer example: 371 sku: type: string example: KIT-STARTER title: type: string example: null nullable: true published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: [] subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: string example: null nullable: true extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 40 reserved_stock: type: integer example: 0 available_stock: type: integer example: 40 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: '' content: application/json: schema: oneOf: - description: 'Store without bundles' type: object example: message: 'Product bundles are not enabled for this store.' errors: request: - 'Product bundles are not enabled for this store.' properties: message: type: string example: 'Product bundles are not enabled for this store.' errors: type: object properties: request: type: array example: - 'Product bundles are not enabled for this store.' items: type: string - description: 'Published product could not be republished as this bundle' type: object example: message: 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' errors: product: - 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' properties: message: type: string example: 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' errors: type: object properties: product: type: array example: - 'The product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup.' items: type: string - description: 'Variant cannot be a component' type: object example: message: 'Variant 2310 cannot be a component: it must be a one-time variant of another product of this store that is not a bundle and is published, scheduled or queued.' errors: components.1.variant_id: - 'Variant 2310 cannot be a component: it must be a one-time variant of another product of this store that is not a bundle and is published, scheduled or queued.' properties: message: type: string example: 'Variant 2310 cannot be a component: it must be a one-time variant of another product of this store that is not a bundle and is published, scheduled or queued.' errors: type: object properties: components.1.variant_id: type: array example: - 'Variant 2310 cannot be a component: it must be a one-time variant of another product of this store that is not a bundle and is published, scheduled or queued.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: components: type: array description: 'Up to 100.' items: type: object properties: variant_id: type: integer description: 'A variant id from `GET /variants`.' example: 2301 quantity: type: integer description: 'Units of the variant in one bundle.' example: 2 required: - variant_id - quantity required: - components delete: summary: 'Turn a bundle back into a single product' operationId: turnABundleBackIntoASingleProduct description: "Turns a bundle back into a single product, as switching the product type in\nthe editor does: the components are dropped from every variant, and the\nproduct's own shipping and stock settings apply again. Fires the\n`product_updated` webhook.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 371 name: 'Starter kit' slug: starter-kit status: published published: true price: 6900 formatted_price: $69.00 stock: 40 available_stock: 40 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2380 options: [] bundle: null shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/starter-kit' variants: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 371 name: type: string example: 'Starter kit' slug: type: string example: starter-kit status: type: string example: published published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 stock: type: integer example: 40 available_stock: type: integer example: 40 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2380 options: type: array example: [] bundle: type: string example: null nullable: true shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/starter-kit' variants: type: array example: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 2380 product_id: type: integer example: 371 sku: type: string example: KIT-STARTER title: type: string example: null nullable: true published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: [] subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: string example: null nullable: true extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 40 reserved_stock: type: integer example: 0 available_stock: type: integer example: 40 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Not a bundle' content: application/json: schema: type: object example: message: 'This product is not a bundle.' errors: product: - 'This product is not a bundle.' properties: message: type: string example: 'This product is not a bundle.' errors: type: object properties: product: type: array example: - 'This product is not a bundle.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products parameters: - in: path name: id description: 'The product id.' example: 371 required: true schema: type: integer '/public/v1/products/{id}/bundle/components': post: summary: 'Add or update a bundle component' operationId: addOrUpdateABundleComponent description: "Adds one variant to a bundle, or changes the quantity of one it already\nholds; the other components stay. The same rules as\n`PUT /products/{id}/bundle` apply, and the product must already be a bundle.\nFires the `product_updated` webhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 371 name: 'Starter kit' slug: starter-kit status: published published: true price: 6900 formatted_price: $69.00 stock: 40 available_stock: 40 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2380 options: [] bundle: components: - variant_id: 2301 quantity: 2 - variant_id: 2315 quantity: 1 shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/starter-kit' variants: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 371 name: type: string example: 'Starter kit' slug: type: string example: starter-kit status: type: string example: published published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 stock: type: integer example: 40 available_stock: type: integer example: 40 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2380 options: type: array example: [] bundle: type: object properties: components: type: array example: - variant_id: 2301 quantity: 2 - variant_id: 2315 quantity: 1 items: type: object properties: variant_id: type: integer example: 2301 quantity: type: integer example: 2 shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/starter-kit' variants: type: array example: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 2380 product_id: type: integer example: 371 sku: type: string example: KIT-STARTER title: type: string example: null nullable: true published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: [] subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: string example: null nullable: true extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 40 reserved_stock: type: integer example: 0 available_stock: type: integer example: 40 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Not a bundle' content: application/json: schema: type: object example: message: 'This product is not a bundle. Make it one with PUT /products/{id}/bundle.' errors: product: - 'This product is not a bundle. Make it one with PUT /products/{id}/bundle.' properties: message: type: string example: 'This product is not a bundle. Make it one with PUT /products/{id}/bundle.' errors: type: object properties: product: type: array example: - 'This product is not a bundle. Make it one with PUT /products/{id}/bundle.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products requestBody: required: true content: application/json: schema: type: object properties: variant_id: type: integer description: 'A variant id from `GET /variants`.' example: 2315 quantity: type: integer description: 'Units of the variant in one bundle.' example: 1 required: - variant_id - quantity parameters: - in: path name: id description: "The bundle's product id." example: 371 required: true schema: type: integer '/public/v1/products/{id}/bundle/components/{variant}': delete: summary: 'Remove a bundle component' operationId: removeABundleComponent description: "Takes one variant out of a bundle. A bundle keeps at least one component;\nto turn it back into a single product use `DELETE /products/{id}/bundle`.\nFires the `product_updated` webhook.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 371 name: 'Starter kit' slug: starter-kit status: published published: true price: 6900 formatted_price: $69.00 stock: 40 available_stock: 40 track_inventory: true description: '

Soft cotton tee.

' meta_description: 'Soft cotton tee in five colors.' product_type: physical categories: category_ids: - 7 - 9 primary_category_id: 7 tax: tax_class: default tax_class_id: null tax_code_id: 41 purchase_limits: min_quantity_per_order: 1 max_quantity_per_order: 5 pre_order: pre_order: false estimated_shipping_date: null feed: brand: Northwind condition: new mpn: NW-TEE-01 gtin: null google_product_category_id: 212 include_variant_info_in_title_feed: true gender: unisex age_group: adult personalization_fields: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false download: null default_variant_id: 2380 options: [] bundle: components: - variant_id: 2301 quantity: 2 shipping: requires_shipping: true auto_fulfill_order: false hs_code: '6109.10' country_of_origin: pt custom_fields: '12': Cotton '13': 'https://cdn.example.com/media/care-guide.pdf' images: main_image: 'https://cdn.example.com/tee.jpg' main_image_large: 'https://cdn.example.com/tee-large.jpg' main: id: 901 url: 'https://cdn.example.com/tee.jpg' alt_text: 'Black cotton tee' extra: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null url: 'https://store.example.com/product/starter-kit' variants: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' created_at: '2026-01-14T09:00:00.000000Z' deleted_at: null updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 371 name: type: string example: 'Starter kit' slug: type: string example: starter-kit status: type: string example: published published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 stock: type: integer example: 40 available_stock: type: integer example: 40 track_inventory: type: boolean example: true description: type: string example: '

Soft cotton tee.

' meta_description: type: string example: 'Soft cotton tee in five colors.' product_type: type: string example: physical categories: type: object properties: category_ids: type: array example: - 7 - 9 items: type: integer primary_category_id: type: integer example: 7 tax: type: object properties: tax_class: type: string example: default tax_class_id: type: string example: null nullable: true tax_code_id: type: integer example: 41 purchase_limits: type: object properties: min_quantity_per_order: type: integer example: 1 max_quantity_per_order: type: integer example: 5 pre_order: type: object properties: pre_order: type: boolean example: false estimated_shipping_date: type: string example: null nullable: true feed: type: object properties: brand: type: string example: Northwind condition: type: string example: new mpn: type: string example: NW-TEE-01 gtin: type: string example: null nullable: true google_product_category_id: type: integer example: 212 include_variant_info_in_title_feed: type: boolean example: true gender: type: string example: unisex age_group: type: string example: adult personalization_fields: type: array example: - name: Engraving placeholder: 'Up to 20 letters' help: null required: false items: type: object properties: name: type: string example: Engraving placeholder: type: string example: 'Up to 20 letters' help: type: string example: null nullable: true required: type: boolean example: false download: type: string example: null nullable: true default_variant_id: type: integer example: 2380 options: type: array example: [] bundle: type: object properties: components: type: array example: - variant_id: 2301 quantity: 2 items: type: object properties: variant_id: type: integer example: 2301 quantity: type: integer example: 2 shipping: type: object properties: requires_shipping: type: boolean example: true auto_fulfill_order: type: boolean example: false hs_code: type: string example: '6109.10' country_of_origin: type: string example: pt custom_fields: type: object properties: 12: type: string example: Cotton 13: type: string example: 'https://cdn.example.com/media/care-guide.pdf' images: type: object properties: main_image: type: string example: 'https://cdn.example.com/tee.jpg' main_image_large: type: string example: 'https://cdn.example.com/tee-large.jpg' main: type: object properties: id: type: integer example: 901 url: type: string example: 'https://cdn.example.com/tee.jpg' alt_text: type: string example: 'Black cotton tee' extra: type: array example: - id: 902 url: 'https://cdn.example.com/tee-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 902 url: type: string example: 'https://cdn.example.com/tee-back.jpg' alt_text: type: string example: null nullable: true url: type: string example: 'https://store.example.com/product/starter-kit' variants: type: array example: - id: 2380 product_id: 371 sku: KIT-STARTER title: null published: true price: 6900 formatted_price: $69.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: [] subscription: null download: null images: main: null extra: [] hide_main_image: false hide_extra_images: false stock: 40 reserved_stock: 0 available_stock: 40 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 2380 product_id: type: integer example: 371 sku: type: string example: KIT-STARTER title: type: string example: null nullable: true published: type: boolean example: true price: type: integer example: 6900 formatted_price: type: string example: $69.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: [] subscription: type: string example: null nullable: true download: type: string example: null nullable: true images: type: object properties: main: type: string example: null nullable: true extra: type: array example: [] hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 40 reserved_stock: type: integer example: 0 available_stock: type: integer example: 40 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' created_at: type: string example: '2026-01-14T09:00:00.000000Z' deleted_at: type: string example: null nullable: true updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Product belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Last component' content: application/json: schema: type: object example: message: 'A bundle needs at least one component. Remove the bundle with DELETE /products/{id}/bundle instead.' errors: variant: - 'A bundle needs at least one component. Remove the bundle with DELETE /products/{id}/bundle instead.' properties: message: type: string example: 'A bundle needs at least one component. Remove the bundle with DELETE /products/{id}/bundle instead.' errors: type: object properties: variant: type: array example: - 'A bundle needs at least one component. Remove the bundle with DELETE /products/{id}/bundle instead.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Products parameters: - in: path name: id description: "The bundle's product id." example: 371 required: true schema: type: integer - in: path name: variant description: "The component's variant id." example: 2310 required: true schema: type: integer /public/v1/variants: get: summary: 'List variants' operationId: listVariants description: "Returns every variant of the store's products, archived products excepted,\noldest update first. `published` says whether the variant has a\nstorefront copy. Filter by `sku` to resolve your own identifiers into\nvariant ids. SKUs are not unique within a store, so this always returns an\narray — match on the fields you need rather than assuming a single result.\n\n`stock` is the quantity on hand, `reserved_stock` is held by checkouts in\nprogress, and `available_stock` is what a shopper can still buy.\n\nA published bundle variant holds no stock of its own: `stock`,\n`available_stock` and `track_inventory` are derived from its components. A\ndraft bundle's stock figures mean nothing until it is published.\n\n`compare_at_price` and `formatted_compare_at_price` are null when not set.\n\nRequires the `read_products` token scope." parameters: - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null - in: query name: sku description: 'Returns every variant carrying exactly this SKU; letter case counts.' example: TEE-BLK-M required: false schema: type: string description: 'Returns every variant carrying exactly this SKU; letter case counts.' example: TEE-BLK-M - in: query name: updated_since description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' required: false schema: type: string description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' items: type: object properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Variants '/public/v1/variants/{id}': patch: summary: 'Update a variant' operationId: updateAVariant description: "Changes the variant's price, compare-at price, SKU, weight, dimensions,\nwhether it is on sale (`enabled`) and its own description; only the fields\nyou send change. Prices are integers in the store currency's smallest unit.\nStock has its own endpoint (`PUT /variants/{id}/inventory`). A variant\nwithout a description shows the product's.\n\n`enabled` works only where the store has variant disabling turned on, and\n`description` only where it has variant descriptions turned on; otherwise\nsending the field returns 422 and responses leave it out. Where the store\nuses default variants, the default\nvariant cannot be disabled — choose another default first. Otherwise,\ndisabling the default variant makes the first enabled variant the default,\nas the variant editor does.\n\nWhen the product is published it is republished with the change, Webflow\nincluded, before the response, as the product editor does after a variant\nsave. When Webflow refuses the product nothing is saved (424); when Webflow\nis rate limiting the site nothing is saved and the call answers 503 with\n`Retry-After`. When the change would leave a published product unable to be\npublished, the call answers 422 and nothing is saved. A draft or queued\nproduct keeps the change until it is next published.\n\nFires the `product_updated` webhook when a field changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-BLK-M title: m published: true price: 5400 formatted_price: $54.00 compare_at_price: 5900 formatted_compare_at_price: $59.00 enabled: true description: '

Black, medium.

' options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-BLK-M title: type: string example: m published: type: boolean example: true price: type: integer example: 5400 formatted_price: type: string example: $54.00 compare_at_price: type: integer example: 5900 formatted_compare_at_price: type: string example: $59.00 enabled: type: boolean example: true description: type: string example: '

Black, medium.

' options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Published product cannot be republished' content: application/json: schema: type: object example: message: "The variant's product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup." errors: product: - "The variant's product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup." properties: message: type: string example: "The variant's product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup." errors: type: object properties: product: type: array example: - "The variant's product is published and could not be republished with this change: Product contains shippable variants but store has no shipping zones configured. Move it to draft first, or fix the store setup." items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants requestBody: required: false content: application/json: schema: type: object properties: price: type: integer description: "In the store currency's smallest unit." example: 5400 compare_at_price: type: integer description: 'Send null to clear it.' example: 5900 nullable: true sku: type: string description: 'Send null to clear it. SKUs need not be unique.' example: TEE-BLK-M nullable: true weight: type: integer description: "Hundredths of the store's weight unit, as `dimensions` reports them. Only for a variant that requires shipping; any other variant accepts only its current value or `null`, which changes nothing." example: 18000 nullable: true length: type: integer description: "Hundredths of the store's dimension unit. Only for a variant that requires shipping; any other variant accepts only its current value or `null`, which changes nothing." example: 3000 nullable: true width: type: integer description: "Hundredths of the store's dimension unit. Only for a variant that requires shipping; any other variant accepts only its current value or `null`, which changes nothing." example: 2000 nullable: true height: type: integer description: "Hundredths of the store's dimension unit. Only for a variant that requires shipping; any other variant accepts only its current value or `null`, which changes nothing." example: 200 nullable: true enabled: type: boolean description: 'A disabled variant cannot be bought.' example: true description: type: string description: 'HTML allowed; null falls back to the product description.' example: '

Black, medium.

' nullable: true parameters: - in: path name: id description: 'The variant id.' example: 2302 required: true schema: type: integer '/public/v1/variants/{id}/subscription': put: summary: "Set a variant's subscription billing" operationId: setAVariantsSubscriptionBilling description: "Sells the variant as a subscription: the customer is charged every\n`interval_count` × `interval` instead of once, as the Subscription billing\nmethod in the variant editor does. For a product without options, use its\nonly variant. Replaces the whole subscription: a field left out takes its\ndefault. A billing period longer than the limits below, set in the\ndashboard, reads back unchanged, but you must shorten it before sending it.\nSubscriptions already started keep the terms they started with.\n\n`term` is `renews_until_canceled` (default) or `fixed_term`, which ends\nafter `ends_after` payments (2 to 1000). `renewal_price` sets a different\nprice for renewals than for the first payment; `null`, or a value equal to\nthe variant's price, charges the variant's price for every payment. It works\nonly where the store has renewal prices turned on; otherwise sending it\nreturns 422 and responses leave it out. `charge_shipping_on_renewals`\n(default true) applies only to a variant that requires shipping.\n\nCheckout takes the first payment, and Stripe charges the next one a billing\nperiod later. Stripe allows at most 730 days for that, so a billing period\ncan be at most 730 days, 104 weeks, 23 months or 1 year.\n\nA bundle component, a variant of a bundle that holds a subscription\ncomponent, and, on a product with options, the variant that carries none of\nthem (`options: []`) cannot be billed by subscription.\n\nWorks like Save in the variant editor: a published product is republished\nwith the change before the response (424 when Webflow refuses it, 503 with\n`Retry-After` when Webflow is rate limiting the site, 422 when the change\nwould leave the product unable to be published). Fires the `product_updated`\nwebhook when something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Bundle component' content: application/json: schema: type: object example: message: 'This variant is a component of bundle(s): Gift Box. Remove it from those bundles before billing it by subscription.' errors: variant: - 'This variant is a component of bundle(s): Gift Box. Remove it from those bundles before billing it by subscription.' properties: message: type: string example: 'This variant is a component of bundle(s): Gift Box. Remove it from those bundles before billing it by subscription.' errors: type: object properties: variant: type: array example: - 'This variant is a component of bundle(s): Gift Box. Remove it from those bundles before billing it by subscription.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants requestBody: required: true content: application/json: schema: type: object properties: interval: type: string description: '`day`, `week`, `month` or `year`.' example: month interval_count: type: integer description: 'Number of `interval`s between payments. Defaults to 1.' example: 1 term: type: string description: '`renews_until_canceled` or `fixed_term`.' example: fixed_term ends_after: type: integer description: 'Required for a fixed term: the number of payments, 2 to 1000; `null` for any other term.' example: 12 nullable: true renewal_price: type: integer description: "Price of each renewal, in the store currency's smallest unit; null charges the variant's price." example: 3900 nullable: true charge_shipping_on_renewals: type: boolean description: 'Charge shipping on each renewal. Defaults to true; applies only to a variant that requires shipping; any other variant accepts `true` or `null` and refuses `false`.' example: true nullable: true required: - interval delete: summary: "Remove a variant's subscription billing" operationId: removeAVariantsSubscriptionBilling description: "Turns the variant's subscription off, as choosing One-Time Payment in the\nvariant editor does; its renewal price goes with it. Subscriptions already\nstarted keep renewing.\n\nWorks like Save in the variant editor, with the same 424 and 503 responses\nas `PATCH /variants/{id}`. Fires the `product_updated` webhook\nwhen something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: null download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: string example: null nullable: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants parameters: - in: path name: id description: 'The variant id.' example: 2302 required: true schema: type: integer '/public/v1/variants/{id}/download': put: summary: "Set a variant's digital download" operationId: setAVariantsDigitalDownload description: "Gives the variant a file of its own in place of the product's, as the\nvariant editor's Digital Download does. The product's file is set with\n`PUT /products/{id}/download`; the variant that holds it (the product's\nlowest-`id` variant, the only one of a product without options) refuses this\ncall. Works only where the store has per-variant digital downloads turned\non; otherwise the call returns 422 and variants carry no `download`. A\nbundle variant is refused: bundle buyers get the files of its components.\n\nWorks like Save in the variant editor, with the same 422, 424 and 503\nresponses as `PATCH /variants/{id}`. Fires the `product_updated` webhook\nwhen something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: "Variant holding the product's file" content: application/json: schema: type: object example: message: "This variant holds the product's digital download. Use PUT /products/364/download." errors: variant: - "This variant holds the product's digital download. Use PUT /products/364/download." properties: message: type: string example: "This variant holds the product's digital download. Use PUT /products/364/download." errors: type: object properties: variant: type: array example: - "This variant holds the product's digital download. Use PUT /products/364/download." items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: '' example: 'Pattern, size M (PDF)' url: type: string description: 'An http or https link.' example: 'https://files.example.com/pattern-m.pdf' required: - name - url delete: summary: "Remove a variant's digital download" operationId: removeAVariantsDigitalDownload description: "Returns the variant to the product's file, or to none when the product has\nnone, as clearing the file in the variant editor does. Works only where the\nstore has per-variant digital downloads turned on; otherwise the call\nreturns 422.\n\nWorks like Save in the variant editor, with the same 422, 424 and 503\nresponses as `PATCH /variants/{id}`. Fires the `product_updated` webhook\nwhen something changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: '' content: application/json: schema: oneOf: - description: 'Store without per-variant downloads' type: object example: message: 'Variant digital downloads are not enabled for this store.' errors: request: - 'Variant digital downloads are not enabled for this store.' properties: message: type: string example: 'Variant digital downloads are not enabled for this store.' errors: type: object properties: request: type: array example: - 'Variant digital downloads are not enabled for this store.' items: type: string - description: "Variant holding the product's file" type: object example: message: "This variant holds the product's digital download. Use PUT /products/364/download." errors: variant: - "This variant holds the product's digital download. Use PUT /products/364/download." properties: message: type: string example: "This variant holds the product's digital download. Use PUT /products/364/download." errors: type: object properties: variant: type: array example: - "This variant holds the product's digital download. Use PUT /products/364/download." items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants parameters: - in: path name: id description: 'The variant id.' example: 2302 required: true schema: type: integer '/public/v1/variants/{id}/images': put: summary: "Set a variant's images" operationId: setAVariantsImages description: "Replaces the variant's own main image, its extra images, or both, as the\nvariant editor's image uploaders do, in the shape read under the variant's\n`images`: `{\"id\": …}` keeps an image, `{\"url\": …}` adds one downloaded from a\npublic HTTPS address (up to 4 MB: JPEG, PNG, BMP, GIF, SVG, WebP or AVIF),\neach with an optional `alt_text`. `main` null removes the main image;\n`extra` is the whole gallery in order, up to 25. A variant without images\nof its own shows the product's.\n\n`hide_main_image` and `hide_extra_images` hide the variant's main or extra\nimages altogether, the product's included; they work only where the store\nhas option value images turned on, as in the variant editor; otherwise\nsending them returns 422 and responses leave them out. `alt_text` works as\nin `PUT /products/{id}/images`.\n\nThe product's first variant shows the product's main image, which is set\nwith `PUT /products/{id}/images`; for that variant, leave `main` out or send\nit exactly as read.\n\nWorks like Save in the variant editor, with the same responses as\n`PUT /products/{id}/images`. Fires the `product_updated` webhook when\nsomething changed.\n\nRequires the `write_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_products scope required for this endpoint.' 404: description: 'Variant belongs to another store, its product is archived, or it does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Image could not be downloaded' content: application/json: schema: type: object example: message: 'The file at https://cdn.example.com/tee-m.jpg is a text/html file, which this field does not take.' errors: main.url: - 'The file at https://cdn.example.com/tee-m.jpg is a text/html file, which this field does not take.' properties: message: type: string example: 'The file at https://cdn.example.com/tee-m.jpg is a text/html file, which this field does not take.' errors: type: object properties: main.url: type: array example: - 'The file at https://cdn.example.com/tee-m.jpg is a text/html file, which this field does not take.' items: type: string 424: description: 'Webflow rejected the product' content: application/json: schema: type: object example: message: 'Webflow rejected the product: Validation Failure' properties: message: type: string example: 'Webflow rejected the product: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Variants requestBody: required: false content: application/json: schema: type: object properties: main: type: object description: "The variant's own main image, or null to remove it." properties: id: type: integer description: 'The id of the current main image, to keep it.' example: 911 url: type: string description: 'Required for a new image.' example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string description: '' example: 'Black tee, size M' nullable: true nullable: true extra: type: array description: 'The extra images in order.' items: type: object properties: id: type: integer description: 'The id of one of the current extra images, to keep it.' example: 912 url: type: string description: 'Required for a new image.' example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string description: '' example: 'Back of the tee' nullable: true hide_main_image: type: boolean description: "Hide the variant's main image, the product's included." example: false hide_extra_images: type: boolean description: "Hide the variant's extra images, the product's included." example: false parameters: - in: path name: id description: 'The variant id.' example: 2302 required: true schema: type: integer '/public/v1/variants/{id}/inventory': put: summary: "Set a variant's inventory" operationId: setAVariantsInventory description: "Sets the stock level to an absolute value — this is not an increment. The\nvariant must have inventory tracking enabled and must be published.\n\nSend `expected_stock` to make the write conditional: the update is applied\nonly while `stock` still matches, and a mismatch answers `409`\nwithout changing anything. The conflict response carries `actual_stock`, so\na retry needs no extra read.\n\nThe comparison is against `stock`, not `available_stock`, so checkouts\nholding reserved stock do not cause conflicts.\n\nRequires the `write_inventory` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 2302 product_id: 364 sku: TEE-CLUB-M title: m published: true price: 4900 formatted_price: $49.00 compare_at_price: null formatted_compare_at_price: null enabled: true description: null options: - option_id: 31 option: Size value_id: 88 value: M subscription: interval: month interval_count: 1 term: fixed_term ends_after: 12 renewal_price: 3900 charge_shipping_on_renewals: true download: name: 'Pattern, size M (PDF)' url: 'https://files.example.com/pattern-m.pdf' images: main: id: 911 url: 'https://cdn.example.com/tee-m.jpg' alt_text: 'Black tee, size M' extra: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null hide_main_image: false hide_extra_images: false stock: 120 reserved_stock: 2 available_stock: 118 track_inventory: true requires_shipping: true dimensions: height: 200 length: 3000 width: 2000 weight: 18000 created_at: '2026-01-14T09:00:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' properties: id: type: integer example: 2302 product_id: type: integer example: 364 sku: type: string example: TEE-CLUB-M title: type: string example: m published: type: boolean example: true price: type: integer example: 4900 formatted_price: type: string example: $49.00 compare_at_price: type: string example: null nullable: true formatted_compare_at_price: type: string example: null nullable: true enabled: type: boolean example: true description: type: string example: null nullable: true options: type: array example: - option_id: 31 option: Size value_id: 88 value: M items: type: object properties: option_id: type: integer example: 31 option: type: string example: Size value_id: type: integer example: 88 value: type: string example: M subscription: type: object properties: interval: type: string example: month interval_count: type: integer example: 1 term: type: string example: fixed_term ends_after: type: integer example: 12 renewal_price: type: integer example: 3900 charge_shipping_on_renewals: type: boolean example: true download: type: object properties: name: type: string example: 'Pattern, size M (PDF)' url: type: string example: 'https://files.example.com/pattern-m.pdf' images: type: object properties: main: type: object properties: id: type: integer example: 911 url: type: string example: 'https://cdn.example.com/tee-m.jpg' alt_text: type: string example: 'Black tee, size M' extra: type: array example: - id: 912 url: 'https://cdn.example.com/tee-m-back.jpg' alt_text: null items: type: object properties: id: type: integer example: 912 url: type: string example: 'https://cdn.example.com/tee-m-back.jpg' alt_text: type: string example: null nullable: true hide_main_image: type: boolean example: false hide_extra_images: type: boolean example: false stock: type: integer example: 120 reserved_stock: type: integer example: 2 available_stock: type: integer example: 118 track_inventory: type: boolean example: true requires_shipping: type: boolean example: true dimensions: type: object properties: height: type: integer example: 200 length: type: integer example: 3000 width: type: integer example: 2000 weight: type: integer example: 18000 created_at: type: string example: '2026-01-14T09:00:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_inventory scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_inventory scope required for this endpoint.' 404: description: 'Variant belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: '' content: application/json: schema: oneOf: - description: 'expected_stock no longer matches' type: object example: message: 'Inventory changed before the update could be applied.' expected_stock: 118 actual_stock: 120 properties: message: type: string example: 'Inventory changed before the update could be applied.' expected_stock: type: integer example: 118 actual_stock: type: integer example: 120 - description: 'Variant is not published' type: object example: message: 'Variant must be published before inventory can be updated.' properties: message: type: string example: 'Variant must be published before inventory can be updated.' 422: description: 'Inventory tracking is off for this variant' content: application/json: schema: type: object example: message: 'Inventory tracking is not enabled for this variant.' errors: variant: - 'Inventory tracking is not enabled for this variant.' properties: message: type: string example: 'Inventory tracking is not enabled for this variant.' errors: type: object properties: variant: type: array example: - 'Inventory tracking is not enabled for this variant.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Variants requestBody: required: true content: application/json: schema: type: object properties: stock: type: integer description: 'The new absolute stock level.' example: 120 expected_stock: type: integer description: 'The level you last read. When it no longer matches, the request fails with 409.' example: 118 required: - stock parameters: - in: path name: id description: 'The variant id.' example: 2302 required: true schema: type: integer /public/v1/orders: get: summary: 'List orders' operationId: listOrders description: "Returns the store's orders, oldest update first. Pass `updated_since` for an\nincremental feed. Orders are never removed, so a canceled order appears as\na status change rather than a deletion.\n\nEach entry is the same object `GET /orders/{orderName}` returns, including the\ncustom checkout fields the store marks private.\n\nRequires the `read_orders` token scope." parameters: - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null - in: query name: updated_since description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' required: false schema: type: string description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' responses: 200: description: '' content: application/json: schema: type: object example: data: - order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] meta: per_page: 50 has_more: true next_cursor: eyJpZCI6MTAwMn0 properties: data: type: array example: - order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] items: type: object properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-01T10:12:00.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: true next_cursor: type: string example: eyJpZCI6MTAwMn0 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_orders scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders '/public/v1/orders/{orderName}': get: summary: 'Get an order' operationId: getAnOrder description: "Orders are identified by their `name`, not by an internal id.\n\nA `refunds` array is present only when `payment.status` is `refunded` or\n`partially_refunded`; each entry carries `id`, `amount`, `formatted_amount`,\n`quantity`, `status`, `reason` and `created_at`. Treat its absence as\n\"nothing refunded\" rather than as an error.\n\nSome fields depend on what the order contains. `shipment` is an object\nwhen the order has at least one shippable item and an empty array `[]` when\nit has none, as on a digital-only order.\n\n`shipment.address` and `billing` carry `name`, `email`, `phone`, `address_line_one`, `address_line_two`,\n`city`, `postal_code`, `state`, `country`, `region`, `region_name` and\n`validation_result`, with one `state` field for every country: a US or\nCanadian state as its code (`CA`), free text elsewhere. `region` is the\nregion id (`us-ca`) and `region_name` its name (`California`), both `null`\nwhere the address names no region the store knows.\n\nUnder `payment`, `status` always carries a value and reads `unpaid` before\nthe charge is captured, while `method` and `transaction_id` are `null` until\nthe gateway records them; an offline payment carries its own reference from\nthe start. `billing` and `payment.label` are both `null` only\non an order with no billing details recorded.\n\n`details.custom_fields` carries every custom checkout field the shopper\nfilled in, including the ones the store marks private — marking a field\nprivate hides it from the shopper, not from this API. When a private field\nhas the same name as a public one, the private value is returned. The map is always an object, empty when the\norder carries none.\n\nRequires the `read_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-01T10:12:00.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_orders scope required for this endpoint.' 404: description: 'Unknown order' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/tracking': patch: summary: "Update an order's tracking" operationId: updateAnOrdersTracking description: "Adds or replaces the shipping carrier and tracking details on an order. Send\na field as `null` to clear it. The order must contain at least one shippable\nitem, and at least one of `shipping_carrier`, `tracking_number` or\n`tracking_url` must be present.\n\nWhere the details land depends on how many fulfillments the order has. With\nmore than one, or when the order is partially fulfilled, `fulfillment_id` is\nrequired and targets that fulfillment. With exactly one, omit it and the\ndetails go to that fulfillment. With none, they go to the order's shipment.\n\nFires the `order_updated` webhook and moves the order's `updated_at` on every\ncall, also when the values sent are the ones already stored.\n\nRead the tracking back from where it was written: anything stored on a\nfulfillment comes back under the matching entry in `fulfillments[]`, and\n`shipment.tracking_url`, `shipment.tracking_number` and `shipment.provider`\nare always `null` once the order has any fulfillment.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: provider: DHL tracking_number: JD014600006281230542 tracking_url: 'https://www.dhl.com/track?id=JD014600006281230542' address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: provider: type: string example: DHL tracking_number: type: string example: JD014600006281230542 tracking_url: type: string example: 'https://www.dhl.com/track?id=JD014600006281230542' address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: '' content: application/json: schema: oneOf: - description: 'Nothing to ship' type: object example: message: 'Order has no shippable items.' errors: order: - 'Order has no shippable items.' properties: message: type: string example: 'Order has no shippable items.' errors: type: object properties: order: type: array example: - 'Order has no shippable items.' items: type: string - description: 'No tracking field sent' type: object example: message: 'At least one supported field is required.' errors: request: - 'At least one supported field is required.' properties: message: type: string example: 'At least one supported field is required.' errors: type: object properties: request: type: array example: - 'At least one supported field is required.' items: type: string - description: 'fulfillment_id omitted on a multi-fulfillment order' type: object example: message: 'The fulfillment id field is required.' errors: fulfillment_id: - 'The fulfillment id field is required.' properties: message: type: string example: 'The fulfillment id field is required.' errors: type: object properties: fulfillment_id: type: array example: - 'The fulfillment id field is required.' items: type: string - description: 'Fulfillment belongs to another order' type: object example: message: 'The fulfillment_id does not belong to this order.' errors: fulfillment_id: - 'The fulfillment_id does not belong to this order.' properties: message: type: string example: 'The fulfillment_id does not belong to this order.' errors: type: object properties: fulfillment_id: type: array example: - 'The fulfillment_id does not belong to this order.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders requestBody: required: false content: application/json: schema: type: object properties: shipping_carrier: type: string description: 'The carrier name shown to the customer.' example: DHL nullable: true tracking_number: type: string description: '' example: JD014600006281230542 nullable: true tracking_url: type: string description: 'Must be a valid URL.' example: 'https://www.dhl.com/track?id=JD014600006281230542' nullable: true fulfillment_id: type: integer description: 'Required when the order has multiple fulfillments or is partially fulfilled.' example: 91 nullable: true parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/fulfill': post: summary: 'Fulfill an order' operationId: fulfillAnOrder description: "Marks the whole order fulfilled and, when `send_notification` is true, emails\nthe customer. Tracking details sent here are stored alongside the fulfillment,\nso a shipment can be recorded in one call.\n\nOnly whole-order fulfillment is supported; items cannot be fulfilled one by\none through this endpoint. As in the dashboard, a refunded order can still be\nfulfilled. Fires the `order_updated` and `order_fulfillment_updated` webhooks.\n\nEach `fulfillments[].items[].order_item_id` identifies the order line it\ncovers; it is not repeated in `items[]`, which carries no id. A line covering\na bundle also carries `components[]`, one entry per bundled variant with its\n`name` and `quantity`; their `live_product_variant_id` identifies the\ncomponent within the order and is not a variant id from `GET /variants`.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: fulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: - id: 91 provider: DHL tracking_number: JD014600006281230542 tracking_url: 'https://www.dhl.com/track?id=JD014600006281230542' fulfilled_at: '2026-08-14T10:05:12.000000Z' items: - order_item_id: 5501 name: 'Classic Tee' quantity: 1 billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 1 remaining_fulfillment_quantity: 0 fulfillment_state: fulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-14T10:05:12.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: '2026-08-14T10:05:12.000000Z' disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: fulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: - id: 91 provider: DHL tracking_number: JD014600006281230542 tracking_url: 'https://www.dhl.com/track?id=JD014600006281230542' fulfilled_at: '2026-08-14T10:05:12.000000Z' items: - order_item_id: 5501 name: 'Classic Tee' quantity: 1 items: type: object properties: id: type: integer example: 91 provider: type: string example: DHL tracking_number: type: string example: JD014600006281230542 tracking_url: type: string example: 'https://www.dhl.com/track?id=JD014600006281230542' fulfilled_at: type: string example: '2026-08-14T10:05:12.000000Z' items: type: array example: - order_item_id: 5501 name: 'Classic Tee' quantity: 1 items: type: object properties: order_item_id: type: integer example: 5501 name: type: string example: 'Classic Tee' quantity: type: integer example: 1 billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 1 remaining_fulfillment_quantity: 0 fulfillment_state: fulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 1 remaining_fulfillment_quantity: type: integer example: 0 fulfillment_state: type: string example: fulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-14T10:05:12.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: '2026-08-14T10:05:12.000000Z' disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: 'Order is in a status that cannot be fulfilled' content: application/json: schema: type: object example: message: 'Order cannot be fulfilled from status canceled.' properties: message: type: string example: 'Order cannot be fulfilled from status canceled.' 422: description: 'Tracking link is not a URL' content: application/json: schema: type: object example: message: 'The tracking url field must be a valid URL.' errors: tracking_url: - 'The tracking url field must be a valid URL.' properties: message: type: string example: 'The tracking url field must be a valid URL.' errors: type: object properties: tracking_url: type: array example: - 'The tracking url field must be a valid URL.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders requestBody: required: false content: application/json: schema: type: object properties: shipping_carrier: type: string description: '' example: DHL nullable: true tracking_number: type: string description: '' example: JD014600006281230542 nullable: true tracking_url: type: string description: '' example: 'https://www.dhl.com/track?id=JD014600006281230542' nullable: true send_notification: type: boolean description: 'Emails the customer that the order shipped. Defaults to false.' example: true parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/unfulfill': post: summary: 'Unfulfill an order' operationId: unfulfillAnOrder description: "Returns a fulfilled or partially fulfilled order to the unfulfilled state.\nTracking stored on the order's shipment is kept; tracking recorded on a\nfulfillment is removed with the fulfillment. Fires the `order_updated` and\n`order_fulfillment_updated` webhooks.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: provider: DHL tracking_number: JD014600006281230542 tracking_url: 'https://www.dhl.com/track?id=JD014600006281230542' address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-14T10:41:03.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: provider: type: string example: DHL tracking_number: type: string example: JD014600006281230542 tracking_url: type: string example: 'https://www.dhl.com/track?id=JD014600006281230542' address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-14T10:41:03.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: 'Order was never fulfilled' content: application/json: schema: type: object example: message: 'Order cannot be unfulfilled from status unfulfilled.' properties: message: type: string example: 'Order cannot be unfulfilled from status unfulfilled.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/cancel': post: summary: 'Cancel an order' operationId: cancelAnOrder description: "Moves the order to the canceled status, fires the `order_updated` webhook\nand sends the cancellation email, as canceling in the dashboard does.\n\nThis is a status change only. It does **not** refund the payment, return\nstock to inventory, remove fulfillments, or cancel subscriptions created by\nthe order — handle those separately if your flow needs them.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: canceled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-14T11:02:47.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: canceled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-14T11:02:47.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: 'Order already reached a final status' content: application/json: schema: type: object example: message: 'Order cannot be canceled from status canceled.' properties: message: type: string example: 'Order cannot be canceled from status canceled.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/mark-paid': post: summary: 'Mark an order as paid' operationId: markAnOrderAsPaid description: "Records the payment for an order placed with an offline payment method, the\nsame as **Mark as paid** in the dashboard: the order moves to `unfulfilled`,\nstock is taken, the order is sent to your shipping and tax providers, and,\nwhen `send_notification` is true, the customer gets the payment confirmation\nemail.\n\nOnly orders paid offline that are still unpaid can be marked paid. Fires the\n`order_payment_updated` webhook.\n\nWhen the order was marked unpaid earlier and the stock returned then has since\nsold, the call answers 409 and the order stays unpaid.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-01T10:12:00.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: '' content: application/json: schema: oneOf: - description: 'Order was not paid offline' type: object example: message: 'Only orders paid offline can be marked paid.' properties: message: type: string example: 'Only orders paid offline can be marked paid.' - description: 'Order is already paid or canceled' type: object example: message: 'Order cannot be marked paid from payment status paid and status unfulfilled.' properties: message: type: string example: 'Order cannot be marked paid from payment status paid and status unfulfilled.' - description: 'Stock returned when the order was marked unpaid has since sold' type: object example: message: 'Not enough stock to mark the order paid: T-shirt: Red needs 2, 0 available.' properties: message: type: string example: 'Not enough stock to mark the order paid: T-shirt: Red needs 2, 0 available.' 422: description: 'Not a boolean' content: application/json: schema: type: object example: message: 'The send notification field must be true or false.' errors: send_notification: - 'The send notification field must be true or false.' properties: message: type: string example: 'The send notification field must be true or false.' errors: type: object properties: send_notification: type: array example: - 'The send notification field must be true or false.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders requestBody: required: false content: application/json: schema: type: object properties: send_notification: type: boolean description: 'Emails the customer the payment confirmation. Defaults to false.' example: true parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/mark-unpaid': post: summary: 'Mark an order as unpaid' operationId: markAnOrderAsUnpaid description: "Reverses **Mark as paid** for an order placed with an offline payment method:\npayment status goes back to `unpaid` and the order to the status the offline\npayment method places new orders in (`pending` or `unfulfilled`), its stock is\nreturned to inventory, it no longer counts toward your order quota, and its\ntransaction is removed from your tax provider. Emails already sent are not\nrecalled. Marking the order paid again runs the payment steps afresh.\n\nOnly paid, unfulfilled orders paid offline and without refunds can be marked\nunpaid. Fires the `order_payment_updated` webhook.\n\nRequires the `write_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: pending currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Bank transfer' status: unpaid method: offline transaction_id: null details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: pending currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Bank transfer' status: type: string example: unpaid method: type: string example: offline transaction_id: type: string example: null nullable: true details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-01T10:12:00.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: '' content: application/json: schema: oneOf: - description: 'Order was not paid offline' type: object example: message: 'Only orders paid offline can be marked unpaid.' properties: message: type: string example: 'Only orders paid offline can be marked unpaid.' - description: 'Order is fulfilled, refunded or not paid' type: object example: message: 'Order cannot be marked unpaid from payment status paid and status fulfilled.' properties: message: type: string example: 'Order cannot be marked unpaid from payment status paid and status fulfilled.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/refunds': get: summary: "List an order's refunds" operationId: listAnOrdersRefunds description: "Every refund recorded on the order, oldest first, including `failed` ones —\nunlike the order's `refunds` field, which lists them only once the order is\nrefunded.\n\nRequires the `read_orders` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 88 amount: 1500 formatted_amount: $15.00 quantity: null status: completed reason: 'Damaged in transit' created_at: '2026-10-06T09:00:00.000000Z' properties: data: type: array example: - id: 88 amount: 1500 formatted_amount: $15.00 quantity: null status: completed reason: 'Damaged in transit' created_at: '2026-10-06T09:00:00.000000Z' items: type: object properties: id: type: integer example: 88 amount: type: integer example: 1500 formatted_amount: type: string example: $15.00 quantity: type: string example: null nullable: true status: type: string example: completed reason: type: string example: 'Damaged in transit' created_at: type: string example: '2026-10-06T09:00:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_orders scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_orders scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string '/public/v1/orders/{orderName}/refund': post: summary: 'Refund an order' operationId: refundAnOrder description: "Refunds any paid order, the same as **Issue Refund** in the dashboard. Leave\n`amount` out to refund everything not yet refunded, or send part of it;\nfurther partial refunds are allowed until the total is reached. Send an\n`Idempotency-Key` header to make a retry safe: a repeat with the same key\nwithin a day gets the first answer back (`Idempotency-Replay: true`) instead\nof a second refund, including a 424 whose outcome is unknown; the same key\nwith a different body is a 422. Only a refund that went through, or whose\noutcome is unknown, is remembered; any other refusal (409, 422, or a 424 the\ngateway refused) can be retried with the same key. The order's\n`payment.status` becomes `partially_refunded` or `refunded`, and the\n`refund_issued` webhook fires.\n\nWhat happens to the money depends on how the order was paid:\n\n- Stripe: the amount goes back to the customer's card.\n- PayPal: refund the order in PayPal, as in the dashboard; CartGenie records\n the refund when PayPal reports it. The call answers 409.\n- An offline payment method: CartGenie cannot move the money. The refund is\n recorded so the order, reports and webhooks reflect it — return the money\n to the customer yourself.\n\nWhen the gateway turns the refund down the call answers 424 and the refund\nis recorded as `failed`.\n\n`restock: true` returns the order's items to inventory with a full refund,\nwhere the store has returning items to inventory turned on; it is refused with 422 on a partial\nrefund or when the order has no tracked items left to return. Items go back\nafter the money does, so if that step fails the refund still stands and\n`restocked` says whether the items are back — when it is `false`, return\nthem in the dashboard. A refund does not cancel the order or its\nsubscriptions.\n\nRequires the `write_refunds` token scope." parameters: - in: header name: Idempotency-Key description: '' example: zap-run-42 schema: type: string responses: 201: description: '' content: application/json: schema: type: object example: id: 88 amount: 1500 formatted_amount: $15.00 quantity: null status: completed reason: 'Damaged in transit' created_at: '2026-10-06T09:00:00.000000Z' restocked: false properties: id: type: integer example: 88 amount: type: integer example: 1500 formatted_amount: type: string example: $15.00 quantity: type: string example: null nullable: true status: type: string example: completed reason: type: string example: 'Damaged in transit' created_at: type: string example: '2026-10-06T09:00:00.000000Z' restocked: type: boolean example: false 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_refunds scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_refunds scope required for this endpoint.' 404: description: 'Order belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: '' content: application/json: schema: oneOf: - description: 'Order already refunded' type: object example: message: 'Order cannot be refunded from payment status refunded.' properties: message: type: string example: 'Order cannot be refunded from payment status refunded.' - description: 'Nothing left to refund' type: object example: message: 'Nothing is left to refund on this order.' properties: message: type: string example: 'Nothing is left to refund on this order.' - description: 'Same Idempotency-Key still in progress' type: object example: message: 'A request with this Idempotency-Key is still in progress; retry once it has answered.' properties: message: type: string example: 'A request with this Idempotency-Key is still in progress; retry once it has answered.' - description: 'Paid with PayPal' type: object example: message: 'Refund PayPal orders in PayPal; the refund is recorded here when PayPal reports it.' properties: message: type: string example: 'Refund PayPal orders in PayPal; the refund is recorded here when PayPal reports it.' - description: 'Payment method removed from the store' type: object example: message: "The store no longer has the order's payment method set up, so the refund cannot be recorded." properties: message: type: string example: "The store no longer has the order's payment method set up, so the refund cannot be recorded." 422: description: '' content: application/json: schema: oneOf: - description: 'More than is left' type: object example: message: 'The amount may not be greater than 1500.' errors: amount: - 'The amount may not be greater than 1500.' properties: message: type: string example: 'The amount may not be greater than 1500.' errors: type: object properties: amount: type: array example: - 'The amount may not be greater than 1500.' items: type: string - description: 'Store does not return items on refund' type: object example: message: 'Returning items to inventory is not enabled for this store.' errors: restock: - 'Returning items to inventory is not enabled for this store.' properties: message: type: string example: 'Returning items to inventory is not enabled for this store.' errors: type: object properties: restock: type: array example: - 'Returning items to inventory is not enabled for this store.' items: type: string - description: 'Nothing to return to inventory' type: object example: message: 'The order has no tracked items left to return to inventory; leave restock out.' errors: restock: - 'The order has no tracked items left to return to inventory; leave restock out.' properties: message: type: string example: 'The order has no tracked items left to return to inventory; leave restock out.' errors: type: object properties: restock: type: array example: - 'The order has no tracked items left to return to inventory; leave restock out.' items: type: string - description: 'Idempotency key reused with a different request' type: object example: message: 'This key was used with a different request.' errors: Idempotency-Key: - 'This key was used with a different request.' properties: message: type: string example: 'This key was used with a different request.' errors: type: object properties: Idempotency-Key: type: array example: - 'This key was used with a different request.' items: type: string - description: 'Restock with a partial refund' type: object example: message: 'Items go back to inventory only with a full refund; leave restock out.' errors: restock: - 'Items go back to inventory only with a full refund; leave restock out.' properties: message: type: string example: 'Items go back to inventory only with a full refund; leave restock out.' errors: type: object properties: restock: type: array example: - 'Items go back to inventory only with a full refund; leave restock out.' items: type: string 424: description: '' content: application/json: schema: oneOf: - description: 'Gateway refused the refund' type: object example: message: 'The payment gateway refused the refund.' properties: message: type: string example: 'The payment gateway refused the refund.' - description: 'Refund could not be completed' type: object example: message: 'The refund could not be completed, and the money may have moved. Check the payment gateway before retrying.' properties: message: type: string example: 'The refund could not be completed, and the money may have moved. Check the payment gateway before retrying.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Orders requestBody: required: false content: application/json: schema: type: object properties: amount: type: integer description: "In the order currency's smallest unit; defaults to everything not yet refunded." example: 1500 restock: type: boolean description: 'Return the items to inventory.' example: false reason: type: string description: 'Kept with the refund and returned as `reason`.' example: 'Damaged in transit' nullable: true parameters: - in: path name: orderName description: "The order's `name`." example: '1002' required: true schema: type: string /public/v1/webhooks/sample: get: summary: 'Get sample deliveries for an event' operationId: getSampleDeliveriesForAnEvent description: "Returns delivery bodies for one event in exactly the shape a live delivery\ncarries, so you can map fields before the first real event arrives.\n\n`new_order`, `order_updated`, `order_fulfillment_updated`,\n`order_payment_updated` and `refund_issued` return up to 3 of the store's\nlatest matching orders — orders with a fulfillment for\n`order_fulfillment_updated`, orders placed with an offline payment method\nfor `order_payment_updated`, orders with a completed refund for `refund_issued`.\nWhen the store has none, and for every other event, the\nresponse holds one representative example instead of a real record.\n\nDeliveries keep a format of their own, which differs from this API's\nresponses for the same record: product and category `status` is a display\nlabel (`Draft`, `Sync Error`) rather than the API's value; product,\ncategory, customer and discount timestamps carry a `+00:00` offset while\norder timestamps carry `Z`; and addresses carry `state` as a state name or\na region id (`us-ca`), next to `region` and `region_name`, where\nthe API answers with the state code (`CA`). Map fields from these samples,\nnot from the API's responses.\n\nThe token needs the read scope that matches the event: `read_orders` for\norder, refund, fulfillment and abandoned-cart events, `read_customers`,\n`read_subscriptions`, `read_discounts`, `read_categories`, or\n`read_products` for product and inventory events. Its owner needs the\nmatching view permission in the store." parameters: - in: query name: event description: 'The event to sample, from the list under "Create a webhook subscription".' example: new_category required: true schema: type: string description: 'The event to sample, from the list under "Create a webhook subscription".' example: new_category responses: 200: description: '' content: application/json: schema: type: object example: data: - type: new_category payload: name: Mugs slug: mugs status: Published published_at: '2025-05-28T11:00:00+00:00' created_at: '2025-05-25T10:00:00+00:00' updated_at: '2025-05-28T11:00:00+00:00' description: null meta_description: null properties: data: type: array example: - type: new_category payload: name: Mugs slug: mugs status: Published published_at: '2025-05-28T11:00:00+00:00' created_at: '2025-05-25T10:00:00+00:00' updated_at: '2025-05-28T11:00:00+00:00' description: null meta_description: null items: type: object properties: type: type: string example: new_category payload: type: object properties: name: type: string example: Mugs slug: type: string example: mugs status: type: string example: Published published_at: type: string example: '2025-05-28T11:00:00+00:00' created_at: type: string example: '2025-05-25T10:00:00+00:00' updated_at: type: string example: '2025-05-28T11:00:00+00:00' description: type: string example: null nullable: true meta_description: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token lacks the scope for this event' content: application/json: schema: type: object example: message: 'This token does not have the read_categories scope required for the new_category event.' properties: message: type: string example: 'This token does not have the read_categories scope required for the new_category event.' 422: description: 'Unknown event' content: application/json: schema: type: object example: message: 'The selected event is invalid.' errors: event: - 'The selected event is invalid.' properties: message: type: string example: 'The selected event is invalid.' errors: type: object properties: event: type: array example: - 'The selected event is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks /public/v1/webhooks: get: summary: 'List webhook subscriptions' operationId: listWebhookSubscriptions description: 'Requires the `read_webhooks` token scope.' parameters: - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 7 name: 'Order sync' url: 'https://example.com/hooks/cartgenie' description: null enabled: true events: - new_order - order_updated last_dispatched_at: '2026-08-14T09:12:00.000000Z' created_at: '2026-07-01T12:00:00.000000Z' updated_at: '2026-08-14T09:12:00.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 7 name: 'Order sync' url: 'https://example.com/hooks/cartgenie' description: null enabled: true events: - new_order - order_updated last_dispatched_at: '2026-08-14T09:12:00.000000Z' created_at: '2026-07-01T12:00:00.000000Z' updated_at: '2026-08-14T09:12:00.000000Z' items: type: object properties: id: type: integer example: 7 name: type: string example: 'Order sync' url: type: string example: 'https://example.com/hooks/cartgenie' description: type: string example: null nullable: true enabled: type: boolean example: true events: type: array example: - new_order - order_updated items: type: string last_dispatched_at: type: string example: '2026-08-14T09:12:00.000000Z' created_at: type: string example: '2026-07-01T12:00:00.000000Z' updated_at: type: string example: '2026-08-14T09:12:00.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_webhooks scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks post: summary: 'Create a webhook subscription' operationId: createAWebhookSubscription description: "Registers a URL to receive the events you list. The URL must be a publicly\nreachable HTTPS endpoint — private and loopback addresses are rejected.\n\n## Receiving deliveries\n\nThe request body is `{\"type\": \"\", \"payload\": { ... }}`. Every delivery\ncarries a `Signature` header holding an HMAC-SHA256 of the raw JSON body,\nkeyed with your store's webhook secret from **Settings → Webhooks**. Compute\nthe same digest over the body you received and compare before trusting it.\n\nA delivery is attempted up to three times with exponential backoff and a 10\nsecond timeout, so your endpoint should answer quickly and be safe to call\ntwice with the same event.\n\n## Available events\n\n`new_order`, `order_updated`, `order_fulfillment_updated` (the order was\nfulfilled, partially fulfilled or unfulfilled; `order_updated` fires as\nwell), `new_customer`, `customer_updated`, `new_subscription`,\n`subscription_updated`, `new_subscription_charge`, `new_discount`,\n`discount_updated`, `new_category`, `category_updated`, `new_product`,\n`product_updated`, `new_abandoned_cart`, `refund_issued`,\n`inventory_updated` and `order_payment_updated` (an order paid with an\noffline payment method was marked paid or unpaid).\n\n`new_product` and `product_updated` carry the product's id, name, slug,\nstatus, price, `hs_code`, `country_of_origin`, dates and `url`, not its\nvariants or settings; read `GET /products/{id}` for the whole product.\n\nRequires the `write_webhooks` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 7 name: 'Order sync' url: 'https://example.com/hooks/cartgenie' description: 'Feeds our ERP' enabled: true events: - new_order - order_updated last_dispatched_at: null created_at: '2026-08-14T09:12:00.000000Z' updated_at: '2026-08-14T09:12:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Order sync' url: type: string example: 'https://example.com/hooks/cartgenie' description: type: string example: 'Feeds our ERP' enabled: type: boolean example: true events: type: array example: - new_order - order_updated items: type: string last_dispatched_at: type: string example: null nullable: true created_at: type: string example: '2026-08-14T09:12:00.000000Z' updated_at: type: string example: '2026-08-14T09:12:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_webhooks scope required for this endpoint.' 422: description: 'Endpoint is not publicly reachable over HTTPS' content: application/json: schema: type: object example: message: 'The url must be a publicly reachable HTTPS URL.' errors: url: - 'The url must be a publicly reachable HTTPS URL.' properties: message: type: string example: 'The url must be a publicly reachable HTTPS URL.' errors: type: object properties: url: type: array example: - 'The url must be a publicly reachable HTTPS URL.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'A label for this subscription.' example: 'Order sync' url: type: string description: 'Publicly reachable HTTPS endpoint.' example: 'https://example.com/hooks/cartgenie' description: type: string description: 'Free-form note, up to 10000 characters.' example: 'Feeds our ERP' nullable: true enabled: type: boolean description: 'Defaults to true.' example: true events: type: array description: 'One or more event names from the list above.' example: - new_order - order_updated items: type: string required: - name - url - events '/public/v1/webhooks/{webhook}': get: summary: 'Get a webhook subscription' operationId: getAWebhookSubscription description: 'Requires the `read_webhooks` token scope.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 7 name: 'Order sync' url: 'https://example.com/hooks/cartgenie' description: null enabled: true events: - new_order - order_updated last_dispatched_at: '2026-08-14T09:12:00.000000Z' created_at: '2026-07-01T12:00:00.000000Z' updated_at: '2026-08-14T09:12:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Order sync' url: type: string example: 'https://example.com/hooks/cartgenie' description: type: string example: null nullable: true enabled: type: boolean example: true events: type: array example: - new_order - order_updated items: type: string last_dispatched_at: type: string example: '2026-08-14T09:12:00.000000Z' created_at: type: string example: '2026-07-01T12:00:00.000000Z' updated_at: type: string example: '2026-08-14T09:12:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_webhooks scope required for this endpoint.' 404: description: 'Subscription belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks patch: summary: 'Update a webhook subscription' operationId: updateAWebhookSubscription description: "Only the fields you send are changed. Sending `events` replaces the whole\nlist rather than adding to it.\n\nRequires the `write_webhooks` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 7 name: 'Order sync' url: 'https://example.com/hooks/cartgenie' description: 'Feeds our ERP' enabled: false events: - new_order last_dispatched_at: '2026-08-14T09:12:00.000000Z' created_at: '2026-07-01T12:00:00.000000Z' updated_at: '2026-08-15T08:30:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Order sync' url: type: string example: 'https://example.com/hooks/cartgenie' description: type: string example: 'Feeds our ERP' enabled: type: boolean example: false events: type: array example: - new_order items: type: string last_dispatched_at: type: string example: '2026-08-14T09:12:00.000000Z' created_at: type: string example: '2026-07-01T12:00:00.000000Z' updated_at: type: string example: '2026-08-15T08:30:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_webhooks scope required for this endpoint.' 404: description: 'Subscription belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Endpoint is not publicly reachable over HTTPS' content: application/json: schema: type: object example: message: 'The url must be a publicly reachable HTTPS URL.' errors: url: - 'The url must be a publicly reachable HTTPS URL.' properties: message: type: string example: 'The url must be a publicly reachable HTTPS URL.' errors: type: object properties: url: type: array example: - 'The url must be a publicly reachable HTTPS URL.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: '' example: 'Order sync' url: type: string description: 'Publicly reachable HTTPS endpoint.' example: 'https://example.com/hooks/cartgenie' description: type: string description: '' example: 'Feeds our ERP' nullable: true enabled: type: boolean description: 'Send false to pause deliveries without deleting the subscription.' example: false events: type: array description: 'Replaces the subscribed events.' example: - new_order items: type: string delete: summary: 'Delete a webhook subscription' operationId: deleteAWebhookSubscription description: 'Requires the `write_webhooks` token scope.' parameters: [] responses: 204: description: '' content: application/json: schema: type: object example: {} properties: {} 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_webhooks scope required for this endpoint.' 404: description: 'Subscription belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks parameters: - in: path name: webhook description: 'The subscription id.' example: 7 required: true schema: type: integer '/public/v1/webhooks/{webhook}/test': post: summary: 'Send a test webhook delivery' operationId: sendATestWebhookDelivery description: "Queues one delivery of the chosen event to this subscription, carrying\nrepresentative sample data rather than a real record. Use it to verify your\nendpoint and your signature check before going live.\n\nThe event must already be one this subscription listens for. The destination\nis re-validated at this point, so a URL that has since become unreachable is\nrejected here rather than failing silently later. The test is delivered even\nwhile the subscription is paused (`enabled: false`).\n\nRequires the `write_webhooks` token scope." parameters: [] responses: 202: description: '' content: application/json: schema: type: object example: queued: true event: new_order properties: queued: type: boolean example: true event: type: string example: new_order 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_webhooks scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_webhooks scope required for this endpoint.' 404: description: 'Subscription belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: '' content: application/json: schema: oneOf: - description: 'Subscription does not listen for that event' type: object example: message: 'Event is not configured for this webhook.' errors: event: - 'Event is not configured for this webhook.' properties: message: type: string example: 'Event is not configured for this webhook.' errors: type: object properties: event: type: array example: - 'Event is not configured for this webhook.' items: type: string - description: 'Destination is no longer reachable' type: object example: message: 'Webhook destination must be a publicly reachable HTTPS URL.' errors: url: - 'Webhook destination must be a publicly reachable HTTPS URL.' properties: message: type: string example: 'Webhook destination must be a publicly reachable HTTPS URL.' errors: type: object properties: url: type: array example: - 'Webhook destination must be a publicly reachable HTTPS URL.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Webhooks requestBody: required: true content: application/json: schema: type: object properties: event: type: string description: 'An event this subscription is subscribed to.' example: new_order required: - event parameters: - in: path name: webhook description: 'The subscription id.' example: 7 required: true schema: type: integer /public/v1/categories: get: summary: 'List categories' operationId: listCategories description: "Archived categories are not listed. Pass `slug` or `name` to find one\ncategory; `name` matches case-insensitively. `status` is `draft`,\n`queued`, `published` or `scheduled`, or `sync_error` after Webflow refused\nthe category, or `imported` for a category imported from Webflow that was\nnever saved.\n\nThe list leaves out `product_ids`, which can hold every product of the\nstore; read them from `GET /categories/{category}`.\n\nRequires the `read_categories` token scope." parameters: - in: query name: slug description: 'A category slug.' example: summer-collection required: false schema: type: string description: 'A category slug.' example: summer-collection - in: query name: name description: 'A category name.' example: 'Summer collection' required: false schema: type: string description: 'A category name.' example: 'Summer collection' - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 7 name: 'Summer collection' slug: summer-collection description: 'Light fabrics for hot days.' meta_description: 'Summer clothing' status: published image_url: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: '21': 'Light fabrics for hot days' published_at: '2026-06-01T09:00:00.000000Z' created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-06-01T09:00:00.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 7 name: 'Summer collection' slug: summer-collection description: 'Light fabrics for hot days.' meta_description: 'Summer clothing' status: published image_url: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: 21: 'Light fabrics for hot days' published_at: '2026-06-01T09:00:00.000000Z' created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-06-01T09:00:00.000000Z' items: type: object properties: id: type: integer example: 7 name: type: string example: 'Summer collection' slug: type: string example: summer-collection description: type: string example: 'Light fabrics for hot days.' meta_description: type: string example: 'Summer clothing' status: type: string example: published image_url: type: string example: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: type: object properties: 21: type: string example: 'Light fabrics for hot days' published_at: type: string example: '2026-06-01T09:00:00.000000Z' created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-06-01T09:00:00.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_categories scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Categories post: summary: 'Create a category' operationId: createACategory description: "Saves the category and applies `status` the way the dashboard's save\nbuttons do: `draft` (the default) keeps it off the live site, `queued`\nstages it for the next Webflow site publish, and `published` publishes it\nnow. Stores without Webflow treat `queued` as `published`. On a Webflow\nstore the category is written to the Webflow categories collection before\nthe response returns. `custom_fields` takes the store's category custom\nfields (`GET /categories/custom-fields`), which a category also reads back;\nimages are not set through the API.\n\nFires the `new_category` webhook.\n\nRequires the `write_categories` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 7 name: 'Summer collection' slug: summer-collection description: 'Light fabrics for hot days.' meta_description: 'Summer clothing' status: published product_ids: - 12 - 15 image_url: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: '21': 'Light fabrics for hot days' published_at: '2026-06-01T09:00:00.000000Z' created_at: '2026-06-01T09:00:00.000000Z' updated_at: '2026-06-01T09:00:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Summer collection' slug: type: string example: summer-collection description: type: string example: 'Light fabrics for hot days.' meta_description: type: string example: 'Summer clothing' status: type: string example: published product_ids: type: array example: - 12 - 15 items: type: integer image_url: type: string example: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: type: object properties: 21: type: string example: 'Light fabrics for hot days' published_at: type: string example: '2026-06-01T09:00:00.000000Z' created_at: type: string example: '2026-06-01T09:00:00.000000Z' updated_at: type: string example: '2026-06-01T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_categories scope required for this endpoint.' 422: description: 'Slug already used' content: application/json: schema: type: object example: message: 'The slug has already been taken.' errors: slug: - 'The slug has already been taken.' properties: message: type: string example: 'The slug has already been taken.' errors: type: object properties: slug: type: array example: - 'The slug has already been taken.' items: type: string 424: description: 'Webflow rejected the category' content: application/json: schema: type: object example: message: 'Webflow rejected the category: Validation Failure' properties: message: type: string example: 'Webflow rejected the category: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Categories requestBody: required: true content: application/json: schema: type: object properties: custom_fields: type: object description: 'Values by custom field id from `GET /categories/custom-fields`; every `required` field needs one.' example: 21: 'Light fabrics for hot days' properties: {} name: type: string description: '' example: 'Summer collection' slug: type: string description: 'Unique within the store; normalized as in the dashboard (`Summer Sale!` becomes `summer-sale`) and derived from `name` when left out.' example: summer-collection description: type: string description: '' example: 'Light fabrics for hot days.' nullable: true meta_description: type: string description: '' example: 'Summer clothing' nullable: true status: type: string description: '`draft` (default), `queued` or `published`.' example: published product_ids: type: array description: 'Ids from `GET /products`. A product without a primary category gets this one.' example: - 12 - 15 items: type: integer required: - name '/public/v1/categories/{category}': get: summary: 'Get a category' operationId: getACategory description: 'Requires the `read_categories` token scope.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 7 name: 'Summer collection' slug: summer-collection description: 'Light fabrics for hot days.' meta_description: 'Summer clothing' status: published product_ids: - 12 - 15 image_url: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: '21': 'Light fabrics for hot days' published_at: '2026-06-01T09:00:00.000000Z' created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-06-01T09:00:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Summer collection' slug: type: string example: summer-collection description: type: string example: 'Light fabrics for hot days.' meta_description: type: string example: 'Summer clothing' status: type: string example: published product_ids: type: array example: - 12 - 15 items: type: integer image_url: type: string example: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: type: object properties: 21: type: string example: 'Light fabrics for hot days' published_at: type: string example: '2026-06-01T09:00:00.000000Z' created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-06-01T09:00:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_categories scope required for this endpoint.' 404: description: 'Category belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Categories patch: summary: 'Update a category' operationId: updateACategory description: "Only the fields you send change; `product_ids` replaces the whole list. A\nproduct added without a primary category gets this one as its primary\ncategory, and a product removed from its primary category falls back to\nanother of its categories, as in the product editor.\nWithout `status`, the category keeps its current status and is saved again\nwith it, so a published category is updated in Webflow too. A scheduled,\nimported or `sync_error` category, or a published or queued one on a store\nwhose Webflow categories collection is disconnected, is saved in CartGenie\nonly. A request that changes nothing leaves the category, and its Webflow\nitem, untouched.\n\nFires the `category_updated` webhook once when anything changed — a field,\nthe products or the status.\n\nRequires the `write_categories` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 7 name: 'Summer collection' slug: summer-collection description: 'Light fabrics for hot days.' meta_description: 'Summer clothing' status: published product_ids: - 12 - 15 image_url: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: '21': 'Light fabrics for hot days' published_at: '2026-06-01T09:00:00.000000Z' created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-06-01T09:00:00.000000Z' properties: id: type: integer example: 7 name: type: string example: 'Summer collection' slug: type: string example: summer-collection description: type: string example: 'Light fabrics for hot days.' meta_description: type: string example: 'Summer clothing' status: type: string example: published product_ids: type: array example: - 12 - 15 items: type: integer image_url: type: string example: 'https://cdn.example.com/categories/7/summer.jpg' custom_fields: type: object properties: 21: type: string example: 'Light fabrics for hot days' published_at: type: string example: '2026-06-01T09:00:00.000000Z' created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-06-01T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_categories scope required for this endpoint.' 404: description: 'Category belongs to another store, is archived or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Slug already used' content: application/json: schema: type: object example: message: 'The slug has already been taken.' errors: slug: - 'The slug has already been taken.' properties: message: type: string example: 'The slug has already been taken.' errors: type: object properties: slug: type: array example: - 'The slug has already been taken.' items: type: string 424: description: 'Webflow rejected the category' content: application/json: schema: type: object example: message: 'Webflow rejected the category: Validation Failure' properties: message: type: string example: 'Webflow rejected the category: Validation Failure' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' 503: description: 'Webflow rate limit' content: application/json: schema: type: object example: message: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' properties: message: type: string example: 'Webflow is rate limiting this site. Nothing was saved; retry in a minute.' tags: - Categories requestBody: required: false content: application/json: schema: type: object properties: custom_fields: type: object description: 'Values by custom field id from `GET /categories/custom-fields`; only the fields sent change, `null` clears one.' example: 21: 'Light fabrics for hot days' properties: {} name: type: string description: '' example: 'Summer collection' slug: type: string description: 'Normalized as in the dashboard.' example: summer-collection description: type: string description: '' example: 'Light fabrics for hot days.' nullable: true meta_description: type: string description: '' example: 'Summer clothing' nullable: true status: type: string description: "`draft`, `queued` or `published`. The category's current status is also accepted and changes nothing, so a category fetched with `GET /categories/{category}` can be sent back unchanged." example: published product_ids: type: array description: '' example: - 12 - 15 items: type: integer parameters: - in: path name: category description: 'The category id.' example: 7 required: true schema: type: integer /public/v1/customers: get: summary: 'List customers' operationId: listCustomers description: "Returns the store's customers, oldest update first. A customer is created\nthe first time someone checks out with a new email, or with\n`POST /customers`. Pass\n`updated_since` for an incremental feed; `email` finds one customer by\naddress, case-insensitively, and `search` matches part of a name or email.\n\nRequires the `read_customers` token scope." parameters: - in: query name: email description: 'An email address to look up.' example: jane@example.com required: false schema: type: string description: 'An email address to look up.' example: jane@example.com - in: query name: search description: 'Part of a name or email.' example: jane required: false schema: type: string description: 'Part of a name or email.' example: jane - in: query name: updated_since description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' required: false schema: type: string description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 312 name: 'Jane Doe' email: jane@example.com phone: '+1 555 0100' billing_address: name: 'Jane Doe' phone: '+1 555 0100' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us shipping_address: null created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 312 name: 'Jane Doe' email: jane@example.com phone: '+1 555 0100' billing_address: name: 'Jane Doe' phone: '+1 555 0100' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us shipping_address: null created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' items: type: object properties: id: type: integer example: 312 name: type: string example: 'Jane Doe' email: type: string example: jane@example.com phone: type: string example: '+1 555 0100' billing_address: type: object properties: name: type: string example: 'Jane Doe' phone: type: string example: '+1 555 0100' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us shipping_address: type: string example: null nullable: true created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-05-20T09:00:00.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_customers scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_customers scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers post: summary: 'Create a customer' operationId: createACustomer description: "Adds a customer before they have ordered, for example from a CRM. Their\nfirst checkout with the same email attaches to this customer. Emails are\nunique per store and stored lowercase. No webhook is sent: `new_customer`\nstill fires when the customer's first order is paid.\n\nAn address is read and written with the same fields, so an address taken\nfrom a response can be sent back as it is. It needs `country`, a two-letter\ncode such as `us`. `state` is one field for every country: in the United\nStates and Canada it must be one of the country's states, sent as its code\n(`CA`), region id (`us-ca`) or name (`California`), and always reads back\nas the code; elsewhere it is free text, kept as sent. An address field not\nlisted below is refused with 422.\n\nRequires the `write_customers` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 312 name: 'Jane Doe' email: jane@example.com phone: '+1 555 0100' billing_address: name: 'Jane Doe' phone: '+1 555 0100' address_line_one: '1 Market St' address_line_two: 'Suite 4' city: 'San Francisco' postal_code: '94105' state: CA country: us shipping_address: name: 'Jane Doe' phone: '+1 555 0100' address_line_one: '500 Howard St' address_line_two: 'Floor 2' city: 'San Francisco' postal_code: '94105' state: CA country: us created_at: '2026-10-06T09:00:00.000000Z' updated_at: '2026-10-06T09:00:00.000000Z' properties: id: type: integer example: 312 name: type: string example: 'Jane Doe' email: type: string example: jane@example.com phone: type: string example: '+1 555 0100' billing_address: type: object properties: name: type: string example: 'Jane Doe' phone: type: string example: '+1 555 0100' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: 'Suite 4' city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us shipping_address: type: object properties: name: type: string example: 'Jane Doe' phone: type: string example: '+1 555 0100' address_line_one: type: string example: '500 Howard St' address_line_two: type: string example: 'Floor 2' city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us created_at: type: string example: '2026-10-06T09:00:00.000000Z' updated_at: type: string example: '2026-10-06T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_customers scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_customers scope required for this endpoint.' 422: description: '' content: application/json: schema: oneOf: - description: 'Email already taken' type: object example: message: 'The email has already been taken.' errors: email: - 'The email has already been taken.' properties: message: type: string example: 'The email has already been taken.' errors: type: object properties: email: type: array example: - 'The email has already been taken.' items: type: string - description: 'Unknown US state' type: object example: message: 'The state must be a state of us, as a code, region id or name, such as CA.' errors: billing_address.state: - 'The state must be a state of us, as a code, region id or name, such as CA.' properties: message: type: string example: 'The state must be a state of us, as a code, region id or name, such as CA.' errors: type: object properties: billing_address.state: type: array example: - 'The state must be a state of us, as a code, region id or name, such as CA.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: '' example: 'Jane Doe' nullable: true email: type: string description: '' example: jane@example.com phone: type: string description: '' example: '+1 555 0100' nullable: true billing_address: type: object description: '' properties: name: type: string description: '' example: 'Jane Doe' nullable: true phone: type: string description: '' example: '+1 555 0100' nullable: true address_line_one: type: string description: '' example: '1 Market St' nullable: true address_line_two: type: string description: '' example: 'Suite 4' nullable: true city: type: string description: '' example: 'San Francisco' nullable: true postal_code: type: string description: '' example: '94105' nullable: true state: type: string description: 'Required for `us` and `ca` (code, region id or name of a state); free text elsewhere.' example: CA nullable: true country: type: string description: 'Two-letter country code, required with the address.' example: us nullable: true shipping_address: type: object description: '' properties: name: type: string description: '' example: 'Jane Doe' nullable: true phone: type: string description: '' example: '+1 555 0100' nullable: true address_line_one: type: string description: '' example: '500 Howard St' nullable: true address_line_two: type: string description: '' example: 'Floor 2' nullable: true city: type: string description: '' example: 'San Francisco' nullable: true postal_code: type: string description: '' example: '94105' nullable: true state: type: string description: 'Required for `us` and `ca` (code, region id or name of a state); free text elsewhere.' example: CA nullable: true country: type: string description: 'Two-letter country code, required with the address.' example: us nullable: true required: - email '/public/v1/customers/{customer}': get: summary: 'Get a customer' operationId: getACustomer description: 'Requires the `read_customers` token scope.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 312 name: 'Jane Doe' email: jane@example.com phone: '+1 555 0100' billing_address: null shipping_address: null created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' properties: id: type: integer example: 312 name: type: string example: 'Jane Doe' email: type: string example: jane@example.com phone: type: string example: '+1 555 0100' billing_address: type: string example: null nullable: true shipping_address: type: string example: null nullable: true created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-05-20T09:00:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_customers scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_customers scope required for this endpoint.' 404: description: 'Customer belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers patch: summary: 'Update a customer' operationId: updateACustomer description: "Only the fields you send change; an address you send replaces the stored\none whole, and `null` clears it. An address sent back exactly as it reads\nchanges nothing. Fires the `customer_updated` webhook when something changed.\n\nRequires the `write_customers` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 312 name: 'Jane Smith' email: jane.smith@example.com phone: '+1 555 0101' billing_address: name: 'Jane Smith' phone: '+1 555 0101' address_line_one: '1 Market St' address_line_two: 'Suite 4' city: 'San Francisco' postal_code: '94105' state: CA country: us shipping_address: name: 'Jane Smith' phone: '+1 555 0101' address_line_one: '500 Howard St' address_line_two: 'Floor 2' city: 'San Francisco' postal_code: '94105' state: CA country: us created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-10-06T09:00:00.000000Z' properties: id: type: integer example: 312 name: type: string example: 'Jane Smith' email: type: string example: jane.smith@example.com phone: type: string example: '+1 555 0101' billing_address: type: object properties: name: type: string example: 'Jane Smith' phone: type: string example: '+1 555 0101' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: 'Suite 4' city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us shipping_address: type: object properties: name: type: string example: 'Jane Smith' phone: type: string example: '+1 555 0101' address_line_one: type: string example: '500 Howard St' address_line_two: type: string example: 'Floor 2' city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-10-06T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_customers scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_customers scope required for this endpoint.' 404: description: 'Customer belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Email already taken' content: application/json: schema: type: object example: message: 'The email has already been taken.' errors: email: - 'The email has already been taken.' properties: message: type: string example: 'The email has already been taken.' errors: type: object properties: email: type: array example: - 'The email has already been taken.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: '' example: 'Jane Smith' nullable: true email: type: string description: '' example: jane.smith@example.com phone: type: string description: '' example: '+1 555 0101' nullable: true billing_address: type: object description: '' properties: name: type: string description: '' example: 'Jane Smith' nullable: true phone: type: string description: '' example: '+1 555 0101' nullable: true address_line_one: type: string description: '' example: '1 Market St' nullable: true address_line_two: type: string description: '' example: 'Suite 4' nullable: true city: type: string description: '' example: 'San Francisco' nullable: true postal_code: type: string description: '' example: '94105' nullable: true state: type: string description: 'Required for `us` and `ca` (code, region id or name of a state); free text elsewhere.' example: CA nullable: true country: type: string description: 'Two-letter country code, required with the address.' example: us nullable: true shipping_address: type: object description: '' properties: name: type: string description: '' example: 'Jane Smith' nullable: true phone: type: string description: '' example: '+1 555 0101' nullable: true address_line_one: type: string description: '' example: '500 Howard St' nullable: true address_line_two: type: string description: '' example: 'Floor 2' nullable: true city: type: string description: '' example: 'San Francisco' nullable: true postal_code: type: string description: '' example: '94105' nullable: true state: type: string description: 'Required for `us` and `ca` (code, region id or name of a state); free text elsewhere.' example: CA nullable: true country: type: string description: 'Two-letter country code, required with the address.' example: us nullable: true delete: summary: 'Erase a customer' operationId: eraseACustomer description: "For a data-erasure request. Removes the customer's name, phone, addresses\nand notes, and unlinks their saved payment details; the email becomes\n`erased-{id}@erased.invalid`, including on discount codes issued to that\nemail. Carts with that email that never checked out lose the email and\naddresses. The customer\nand their orders stay, because orders are the store's financial records:\nan order keeps the addresses it was placed with, and its customer email\nreads as the erased one. The customer record at the payment provider is not\ndeleted; remove it there if the request covers it. Refused while the\ncustomer has a subscription that can still charge, since renewals need the\nsaved payment details. There is no undo.\n\nRequires the `write_customers` token scope." parameters: [] responses: 204: description: Erased content: text/plain: schema: type: string example: '' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_customers scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_customers scope required for this endpoint.' 404: description: 'Customer belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: 'Live subscription' content: application/json: schema: type: object example: message: 'The customer has a subscription that can still renew; cancel it before erasing the customer.' properties: message: type: string example: 'The customer has a subscription that can still renew; cancel it before erasing the customer.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers parameters: - in: path name: customer description: 'The customer id.' example: 312 required: true schema: type: integer '/public/v1/customers/{customer}/orders': get: summary: "List a customer's orders" operationId: listACustomersOrders description: "The customer's orders, with the same shape, sort order and `updated_since`\nfilter as `GET /orders`. Needs `read_orders` as well as `read_customers`.\n\nRequires the `read_customers` and `read_orders` token scopes." parameters: - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null - in: query name: updated_since description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' required: false schema: type: string description: 'ISO-8601 date and time with an offset (`Z` or `+02:00`).' example: '2026-08-01T00:00:00Z' responses: 200: description: '' content: application/json: schema: type: object example: data: - order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] meta: per_page: 50 has_more: true next_cursor: eyJpZCI6MTAwMn0 properties: data: type: array example: - order_id: '1002' name: '1002' guid: 01KSNP2NFV6DJWW6MXME27Q0KE status: unfulfilled currency_code: usd coupon_code: null customer_email: john@example.com customer_name: 'John Doe' shipment: tracking_url: null tracking_number: null provider: null address: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null fulfillments: [] billing: name: 'John Doe' email: john@example.com phone: '+14155550123' address_line_one: '1 Market St' address_line_two: null city: 'San Francisco' postal_code: '94105' state: CA country: us region: us-ca region_name: California validation_result: null payment: label: 'Visa ending in 4242' status: paid method: credit_card transaction_id: pi_3Q1example details: custom_fields: 'Gift Message': 'Happy birthday' checkout_type: '' items: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled subtotal: 4900 formatted_subtotal: $49.00 total: 5391 formatted_total: $53.91 discount_total: 0 formatted_discount_total: $0.00 shipping_total: 0 formatted_shipping_total: $0.00 shipping_method_label: Standard tax_total: 491 formatted_tax_total: $4.91 created_at: '2026-08-01T10:12:00.000000Z' updated_at: '2026-08-01T10:12:00.000000Z' placed_at: '2026-08-01T10:12:00.000000Z' fulfilled_at: null disputed_at: null discounts: [] items: type: object properties: order_id: type: string example: '1002' name: type: string example: '1002' guid: type: string example: 01KSNP2NFV6DJWW6MXME27Q0KE status: type: string example: unfulfilled currency_code: type: string example: usd coupon_code: type: string example: null nullable: true customer_email: type: string example: john@example.com customer_name: type: string example: 'John Doe' shipment: type: object properties: tracking_url: type: string example: null nullable: true tracking_number: type: string example: null nullable: true provider: type: string example: null nullable: true address: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true fulfillments: type: array example: [] billing: type: object properties: name: type: string example: 'John Doe' email: type: string example: john@example.com phone: type: string example: '+14155550123' address_line_one: type: string example: '1 Market St' address_line_two: type: string example: null nullable: true city: type: string example: 'San Francisco' postal_code: type: string example: '94105' state: type: string example: CA country: type: string example: us region: type: string example: us-ca region_name: type: string example: California validation_result: type: string example: null nullable: true payment: type: object properties: label: type: string example: 'Visa ending in 4242' status: type: string example: paid method: type: string example: credit_card transaction_id: type: string example: pi_3Q1example details: type: object properties: custom_fields: type: object properties: 'Gift Message': type: string example: 'Happy birthday' checkout_type: type: string example: '' items: type: array example: - sku: TEE-BLK-M quantity: 1 price: 4900 name: 'Classic Tee' slug: classic-tee url: 'https://store.example.com/product/classic-tee' image_url: 'https://cdn.example.com/tee.jpg' subtotal: 4900 options: - name: Size slug: size value: M value_slug: m weight: 180 weight_unit: g height: 2 width: 20 length: 30 downloads: [] has_subscription: false availability: available estimated_shipping_date: null bundle_components: [] fulfilled_quantity: 0 remaining_fulfillment_quantity: 1 fulfillment_state: unfulfilled items: type: object properties: sku: type: string example: TEE-BLK-M quantity: type: integer example: 1 price: type: integer example: 4900 name: type: string example: 'Classic Tee' slug: type: string example: classic-tee url: type: string example: 'https://store.example.com/product/classic-tee' image_url: type: string example: 'https://cdn.example.com/tee.jpg' subtotal: type: integer example: 4900 options: type: array example: - name: Size slug: size value: M value_slug: m items: type: object properties: name: type: string example: Size slug: type: string example: size value: type: string example: M value_slug: type: string example: m weight: type: integer example: 180 weight_unit: type: string example: g height: type: integer example: 2 width: type: integer example: 20 length: type: integer example: 30 downloads: type: array example: [] has_subscription: type: boolean example: false availability: type: string example: available estimated_shipping_date: type: string example: null nullable: true bundle_components: type: array example: [] fulfilled_quantity: type: integer example: 0 remaining_fulfillment_quantity: type: integer example: 1 fulfillment_state: type: string example: unfulfilled subtotal: type: integer example: 4900 formatted_subtotal: type: string example: $49.00 total: type: integer example: 5391 formatted_total: type: string example: $53.91 discount_total: type: integer example: 0 formatted_discount_total: type: string example: $0.00 shipping_total: type: integer example: 0 formatted_shipping_total: type: string example: $0.00 shipping_method_label: type: string example: Standard tax_total: type: integer example: 491 formatted_tax_total: type: string example: $4.91 created_at: type: string example: '2026-08-01T10:12:00.000000Z' updated_at: type: string example: '2026-08-01T10:12:00.000000Z' placed_at: type: string example: '2026-08-01T10:12:00.000000Z' fulfilled_at: type: string example: null nullable: true disputed_at: type: string example: null nullable: true discounts: type: array example: [] meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: true next_cursor: type: string example: eyJpZCI6MTAwMn0 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_customers and read_orders scopes required for this endpoint.' properties: message: type: string example: 'This token does not have the read_customers and read_orders scopes required for this endpoint.' 404: description: 'Customer belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Customers parameters: - in: path name: customer description: 'The customer id.' example: 312 required: true schema: type: integer /public/v1/products/custom-fields: get: summary: 'List product custom fields' operationId: listProductCustomFields description: "The fields the store has added to its products, in the order the dashboard\nshows them. `custom_fields` on `POST /products` and `PATCH /products/{id}`\ntakes a value per field `id`; a `required` field needs one when a product is\ncreated and cannot be cleared, and a `PATCH` is refused while one is still\nempty. A field sent back exactly as it reads is left as it is.\n\nValues by `type`: `text`, `rich_text` (HTML), `email`, `phone`, `link`,\n`video_link` and `color` (`#rrggbb`) are strings; `number` is a number\n(whole when `integer` is true) between `min` and `max`; `switch` is a\nboolean; `date` is an ISO 8601 date (`2026-10-06` or `2026-10-06T09:30:00+02:00`);\n`option` is one of `options`; `reference` is the id of one item from\n`GET /products/custom-fields/{field}/items` and `multi-reference` a list of\nthem; `image` and `file` are the public HTTPS URL of a file CartGenie\ndownloads and stores, and `multi_image` a list of up to 10 image URLs. Any\nother list, a reordered one included, replaces every file of the field.\n`null` clears a field. `min` and `max` bound the length of `text` and\n`rich_text`.\n\nRequires the `read_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 12 label: Material type: option required: true help_text: null options: - Cotton - Linen min: null max: null integer: null - id: 13 label: 'Care guide' type: file required: false help_text: 'PDF, up to 10 MB' options: null min: null max: null integer: null properties: data: type: array example: - id: 12 label: Material type: option required: true help_text: null options: - Cotton - Linen min: null max: null integer: null - id: 13 label: 'Care guide' type: file required: false help_text: 'PDF, up to 10 MB' options: null min: null max: null integer: null items: type: object properties: id: type: integer example: 12 label: type: string example: Material type: type: string example: option required: type: boolean example: true help_text: type: string example: null nullable: true options: type: array example: - Cotton - Linen items: type: string min: type: string example: null nullable: true max: type: string example: null nullable: true integer: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - 'Custom fields' '/public/v1/products/custom-fields/{field}/items': get: summary: "List a product reference field's items" operationId: listAProductReferenceFieldsItems description: "For a `reference` or `multi-reference` field: the items of the Webflow\ncollection it refers to, read from Webflow on each call.\n\nRequires the `read_products` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 64f1c2a9b3e5d7a1c2e3f4a5 name: 'Summer collection' properties: data: type: array example: - id: 64f1c2a9b3e5d7a1c2e3f4a5 name: 'Summer collection' items: type: object properties: id: type: string example: 64f1c2a9b3e5d7a1c2e3f4a5 name: type: string example: 'Summer collection' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_products scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_products scope required for this endpoint.' 404: description: 'Not a reference field of this store' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 424: description: 'Webflow could not be read' content: application/json: schema: type: object example: message: 'The items could not be read from Webflow; try again later.' properties: message: type: string example: 'The items could not be read from Webflow; try again later.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - 'Custom fields' parameters: - in: path name: field description: 'The custom field id.' example: 14 required: true schema: type: integer /public/v1/categories/custom-fields: get: summary: 'List category custom fields' operationId: listCategoryCustomFields description: "The fields the store has added to its categories. `custom_fields` on\n`POST /categories` and `PATCH /categories/{category}` takes a value per\nfield `id`, in the same types as product custom fields.\n\nRequires the `read_categories` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 21 label: 'Banner caption' type: text required: false help_text: null options: null min: null max: 120 integer: null properties: data: type: array example: - id: 21 label: 'Banner caption' type: text required: false help_text: null options: null min: null max: 120 integer: null items: type: object properties: id: type: integer example: 21 label: type: string example: 'Banner caption' type: type: string example: text required: type: boolean example: false help_text: type: string example: null nullable: true options: type: string example: null nullable: true min: type: string example: null nullable: true max: type: integer example: 120 integer: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_categories scope required for this endpoint.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - 'Custom fields' '/public/v1/categories/custom-fields/{field}/items': get: summary: "List a category reference field's items" operationId: listACategoryReferenceFieldsItems description: 'Requires the `read_categories` token scope.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 64f1c2a9b3e5d7a1c2e3f4a5 name: 'Classic Tee' properties: data: type: array example: - id: 64f1c2a9b3e5d7a1c2e3f4a5 name: 'Classic Tee' items: type: object properties: id: type: string example: 64f1c2a9b3e5d7a1c2e3f4a5 name: type: string example: 'Classic Tee' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_categories scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_categories scope required for this endpoint.' 404: description: 'Not a reference field of this store' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 424: description: 'Webflow could not be read' content: application/json: schema: type: object example: message: 'The items could not be read from Webflow; try again later.' properties: message: type: string example: 'The items could not be read from Webflow; try again later.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - 'Custom fields' parameters: - in: path name: field description: 'The custom field id.' example: 22 required: true schema: type: integer /public/v1/discounts: get: summary: 'List discounts' operationId: listDiscounts description: "Pass `code` to find the discount a coupon code belongs to; codes match\ncase-insensitively. Automatic discounts have no code, so filtering by `code`\nleaves them out.\n\nPercentage values are in percent (`12.5` is 12.5%). Fixed values and every\norder-value limit are integers in the store currency's smallest unit, the\nsame as order totals.\n\nRequires the `read_discounts` token scope." parameters: - in: query name: code description: 'A coupon code to look up.' example: SUMMER10 required: false schema: type: string description: 'A coupon code to look up.' example: SUMMER10 - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 41 name: 'Summer sale' notes: null activation: code code: SUMMER10 coupon_name: null type: percentage value: 12.5 formatted_value: 12.5% application_mode: once_per_order target: products category_ids: [] product_ids: - 12 - 15 starts_at: '2026-06-01T00:00:00.000000Z' ends_at: null min_order_value: 5000 formatted_min_order_value: $50.00 max_discount_value: 2000 formatted_max_discount_value: $20.00 min_quantity: 2 max_uses: 100 max_uses_per_customer: 1 times_used: 12 enabled: true created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 41 name: 'Summer sale' notes: null activation: code code: SUMMER10 coupon_name: null type: percentage value: 12.5 formatted_value: 12.5% application_mode: once_per_order target: products category_ids: [] product_ids: - 12 - 15 starts_at: '2026-06-01T00:00:00.000000Z' ends_at: null min_order_value: 5000 formatted_min_order_value: $50.00 max_discount_value: 2000 formatted_max_discount_value: $20.00 min_quantity: 2 max_uses: 100 max_uses_per_customer: 1 times_used: 12 enabled: true created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' items: type: object properties: id: type: integer example: 41 name: type: string example: 'Summer sale' notes: type: string example: null nullable: true activation: type: string example: code code: type: string example: SUMMER10 coupon_name: type: string example: null nullable: true type: type: string example: percentage value: type: number example: 12.5 formatted_value: type: string example: 12.5% application_mode: type: string example: once_per_order target: type: string example: products category_ids: type: array example: [] product_ids: type: array example: - 12 - 15 items: type: integer starts_at: type: string example: '2026-06-01T00:00:00.000000Z' ends_at: type: string example: null nullable: true min_order_value: type: integer example: 5000 formatted_min_order_value: type: string example: $50.00 max_discount_value: type: integer example: 2000 formatted_max_discount_value: type: string example: $20.00 min_quantity: type: integer example: 2 max_uses: type: integer example: 100 max_uses_per_customer: type: integer example: 1 times_used: type: integer example: 12 enabled: type: boolean example: true created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-05-20T09:00:00.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_discounts scope required for this endpoint.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts post: summary: 'Create a discount' operationId: createADiscount description: "Creates a coupon-code discount, or an automatic one where the store has\nautomatic discounts enabled. `value` is in percent for `percentage` and in\nthe currency's smallest unit for `fixed`; `free_shipping` takes no value and\nalways targets shipping. `product_ids` are the ids from `GET /products` and\nmust be published; `category_ids` are the store's category ids.\n\nFires the `new_discount` webhook.\n\nRequires the `write_discounts` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: id: 41 name: 'Summer sale' notes: null activation: code code: SUMMER10 coupon_name: null type: percentage value: 12.5 formatted_value: 12.5% application_mode: once_per_order target: products category_ids: [] product_ids: - 12 - 15 starts_at: '2026-06-01T00:00:00.000000Z' ends_at: null min_order_value: 5000 formatted_min_order_value: $50.00 max_discount_value: 2000 formatted_max_discount_value: $20.00 min_quantity: 2 max_uses: 100 max_uses_per_customer: 1 times_used: 0 enabled: true created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' properties: id: type: integer example: 41 name: type: string example: 'Summer sale' notes: type: string example: null nullable: true activation: type: string example: code code: type: string example: SUMMER10 coupon_name: type: string example: null nullable: true type: type: string example: percentage value: type: number example: 12.5 formatted_value: type: string example: 12.5% application_mode: type: string example: once_per_order target: type: string example: products category_ids: type: array example: [] product_ids: type: array example: - 12 - 15 items: type: integer starts_at: type: string example: '2026-06-01T00:00:00.000000Z' ends_at: type: string example: null nullable: true min_order_value: type: integer example: 5000 formatted_min_order_value: type: string example: $50.00 max_discount_value: type: integer example: 2000 formatted_max_discount_value: type: string example: $20.00 min_quantity: type: integer example: 2 max_uses: type: integer example: 100 max_uses_per_customer: type: integer example: 1 times_used: type: integer example: 0 enabled: type: boolean example: true created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-05-20T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_discounts scope required for this endpoint.' 422: description: 'Code already used by another discount' content: application/json: schema: type: object example: message: 'The coupon code already exists.' errors: code: - 'The coupon code already exists.' properties: message: type: string example: 'The coupon code already exists.' errors: type: object properties: code: type: array example: - 'The coupon code already exists.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: '' example: 'Summer sale' notes: type: string description: 'Internal note.' example: 'Newsletter campaign' nullable: true activation: type: string description: '`code` (default) or `automatic`.' example: code code: type: string description: 'Required for `code` activation. Letters, digits, `-` and `_`; converted to upper case.' example: SUMMER10 coupon_name: type: string description: 'Required for `automatic` activation; shown at checkout.' example: null type: type: string description: '`percentage`, `fixed` or `free_shipping`.' example: percentage value: type: number description: 'Required unless `free_shipping`. 1–100 for `percentage`; an integer in the smallest currency unit for `fixed`.' example: 10.0 application_mode: type: string description: '`once_per_order` (default) or `once_per_item`; only for `fixed`.' example: once_per_order target: type: string description: '`all` (default), `products` or `categories`.' example: all category_ids: type: array description: 'Required when `target` is `categories`.' example: null items: type: integer product_ids: type: array description: 'Required when `target` is `products`.' example: null items: type: integer starts_at: type: string description: 'ISO 8601; defaults to now. A time without an offset is read in the store timezone.' example: '2026-06-01T00:00:00Z' nullable: true ends_at: type: string description: 'ISO 8601, after `starts_at`; null never expires.' example: '2026-08-31T23:59:00Z' nullable: true min_order_value: type: integer description: 'Minimum order subtotal in the smallest currency unit.' example: 5000 nullable: true max_discount_value: type: integer description: 'Cap for `percentage` discounts, in the smallest currency unit.' example: 2000 nullable: true min_quantity: type: integer description: 'Minimum number of items.' example: 2 nullable: true max_uses: type: integer description: 'Total uses before the discount turns off.' example: 100 nullable: true max_uses_per_customer: type: integer description: '' example: 1 nullable: true enabled: type: boolean description: 'Defaults to true.' example: true required: - name - type '/public/v1/discounts/{discount}': get: summary: 'Get a discount' operationId: getADiscount description: 'Requires the `read_discounts` token scope.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 41 name: 'Summer sale' notes: null activation: code code: SUMMER10 coupon_name: null type: percentage value: 10 formatted_value: 10% application_mode: once_per_order target: all category_ids: [] product_ids: [] starts_at: '2026-06-01T00:00:00.000000Z' ends_at: '2026-08-31T23:59:00.000000Z' min_order_value: 5000 formatted_min_order_value: $50.00 max_discount_value: 2000 formatted_max_discount_value: $20.00 min_quantity: 2 max_uses: 100 max_uses_per_customer: 1 times_used: 12 enabled: false created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-05-20T09:00:00.000000Z' properties: id: type: integer example: 41 name: type: string example: 'Summer sale' notes: type: string example: null nullable: true activation: type: string example: code code: type: string example: SUMMER10 coupon_name: type: string example: null nullable: true type: type: string example: percentage value: type: integer example: 10 formatted_value: type: string example: 10% application_mode: type: string example: once_per_order target: type: string example: all category_ids: type: array example: [] product_ids: type: array example: [] starts_at: type: string example: '2026-06-01T00:00:00.000000Z' ends_at: type: string example: '2026-08-31T23:59:00.000000Z' min_order_value: type: integer example: 5000 formatted_min_order_value: type: string example: $50.00 max_discount_value: type: integer example: 2000 formatted_max_discount_value: type: string example: $20.00 min_quantity: type: integer example: 2 max_uses: type: integer example: 100 max_uses_per_customer: type: integer example: 1 times_used: type: integer example: 12 enabled: type: boolean example: false created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-05-20T09:00:00.000000Z' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_discounts scope required for this endpoint.' 404: description: 'Discount belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts patch: summary: 'Update a discount' operationId: updateADiscount description: "Only the fields you send change; the result must still be a valid discount,\nso changing `type` may require `value`, and `target: products` requires\n`product_ids`. Send `enabled: false` to turn the discount off and `true` to\nturn it back on. A discount whose `type` is `free` or whose `target` is\n`variants` keeps that value when updated, and sending it back unchanged is\naccepted; neither value can be chosen for another discount.\n\nFires the `discount_updated` webhook when something changed.\n\nRequires the `write_discounts` token scope." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: id: 41 name: 'Summer sale' notes: 'Extended to August' activation: code code: SUMMER15 coupon_name: null type: percentage value: 15 formatted_value: 15% application_mode: once_per_order target: all category_ids: [] product_ids: [] starts_at: '2026-06-01T00:00:00.000000Z' ends_at: '2026-09-30T23:59:00.000000Z' min_order_value: 5000 formatted_min_order_value: $50.00 max_discount_value: 2000 formatted_max_discount_value: $20.00 min_quantity: 2 max_uses: 200 max_uses_per_customer: 1 times_used: 12 enabled: true created_at: '2026-05-20T09:00:00.000000Z' updated_at: '2026-07-01T10:30:00.000000Z' properties: id: type: integer example: 41 name: type: string example: 'Summer sale' notes: type: string example: 'Extended to August' activation: type: string example: code code: type: string example: SUMMER15 coupon_name: type: string example: null nullable: true type: type: string example: percentage value: type: integer example: 15 formatted_value: type: string example: 15% application_mode: type: string example: once_per_order target: type: string example: all category_ids: type: array example: [] product_ids: type: array example: [] starts_at: type: string example: '2026-06-01T00:00:00.000000Z' ends_at: type: string example: '2026-09-30T23:59:00.000000Z' min_order_value: type: integer example: 5000 formatted_min_order_value: type: string example: $50.00 max_discount_value: type: integer example: 2000 formatted_max_discount_value: type: string example: $20.00 min_quantity: type: integer example: 2 max_uses: type: integer example: 200 max_uses_per_customer: type: integer example: 1 times_used: type: integer example: 12 enabled: type: boolean example: true created_at: type: string example: '2026-05-20T09:00:00.000000Z' updated_at: type: string example: '2026-07-01T10:30:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_discounts scope required for this endpoint.' 404: description: 'Discount belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Code already used by another discount' content: application/json: schema: type: object example: message: 'The coupon code already exists.' errors: code: - 'The coupon code already exists.' properties: message: type: string example: 'The coupon code already exists.' errors: type: object properties: code: type: array example: - 'The coupon code already exists.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: '' example: 'Summer sale' notes: type: string description: '' example: 'Extended to August' nullable: true activation: type: string description: '`code` or `automatic`.' example: code code: type: string description: '' example: SUMMER15 coupon_name: type: string description: '' example: null type: type: string description: '`percentage`, `fixed` or `free_shipping`.' example: percentage value: type: number description: '' example: 15.0 application_mode: type: string description: '' example: once_per_order target: type: string description: '`all`, `products` or `categories`.' example: all category_ids: type: array description: '' example: null items: type: integer product_ids: type: array description: '' example: null items: type: integer starts_at: type: string description: '' example: '2026-06-01T00:00:00Z' nullable: true ends_at: type: string description: '' example: '2026-09-30T23:59:00Z' nullable: true min_order_value: type: integer description: '' example: 5000 nullable: true max_discount_value: type: integer description: '' example: 2000 nullable: true min_quantity: type: integer description: '' example: 2 nullable: true max_uses: type: integer description: '' example: 200 nullable: true max_uses_per_customer: type: integer description: '' example: 1 nullable: true enabled: type: boolean description: '' example: false delete: summary: 'Delete a discount' operationId: deleteADiscount description: "Deletes the discount with every code that applies it, including issued ones.\nCarts holding any of those codes are repriced; orders already placed keep the\ndiscount they were given. There is no undo.\n\nRequires the `write_discounts` token scope." parameters: [] responses: 204: description: Deleted content: text/plain: schema: type: string example: '' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_discounts scope required for this endpoint.' 404: description: 'Discount belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts parameters: - in: path name: discount description: 'The discount id.' example: 41 required: true schema: type: integer '/public/v1/discounts/{discount}/codes': get: summary: "List a discount's codes" operationId: listADiscountsCodes description: "Every code that applies the discount: its own code (`kind: primary`) and the\ncodes issued with `POST /discounts/{discount}/codes` (`kind: generated`). An\nautomatic discount has no code of its own, so its list is empty.\n`times_used` counts the orders placed with that code, paid or awaiting an\noffline payment, so it attributes redemptions to the recipient the code was\nsent to.\n\nRequires the `read_discounts` token scope." parameters: - in: query name: kind description: '`primary` or `generated`.' example: generated required: false schema: type: string description: '`primary` or `generated`.' example: generated - in: query name: limit description: 'Results per page, 1–250.' example: 50 required: false schema: type: integer description: 'Results per page, 1–250.' example: 50 - in: query name: cursor description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null required: false schema: type: string description: 'Opaque cursor from `meta.next_cursor` of the previous page.' example: null responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 905 discount_id: 41 code: WELCOME-7KQ2M9XHTA kind: generated max_uses: 1 times_used: 1 expires_at: '2026-11-05T09:00:00.000000Z' email: jane@example.com created_at: '2026-10-06T09:00:00.000000Z' meta: per_page: 50 has_more: false next_cursor: null properties: data: type: array example: - id: 905 discount_id: 41 code: WELCOME-7KQ2M9XHTA kind: generated max_uses: 1 times_used: 1 expires_at: '2026-11-05T09:00:00.000000Z' email: jane@example.com created_at: '2026-10-06T09:00:00.000000Z' items: type: object properties: id: type: integer example: 905 discount_id: type: integer example: 41 code: type: string example: WELCOME-7KQ2M9XHTA kind: type: string example: generated max_uses: type: integer example: 1 times_used: type: integer example: 1 expires_at: type: string example: '2026-11-05T09:00:00.000000Z' email: type: string example: jane@example.com created_at: type: string example: '2026-10-06T09:00:00.000000Z' meta: type: object properties: per_page: type: integer example: 50 has_more: type: boolean example: false next_cursor: type: string example: null nullable: true 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the read_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the read_discounts scope required for this endpoint.' 404: description: 'Discount belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 422: description: 'Malformed cursor' content: application/json: schema: type: object example: message: 'The cursor is invalid.' errors: cursor: - 'The cursor is invalid.' properties: message: type: string example: 'The cursor is invalid.' errors: type: object properties: cursor: type: array example: - 'The cursor is invalid.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts post: summary: 'Issue discount codes' operationId: issueDiscountCodes description: "Issues `count` unique random codes that each apply the discount, for an email\nor SMS tool that hands one code to each recipient. Every code carries the\ndiscount's own rules (dates, minimum order, total `max_uses` of the discount)\nplus the limits sent here:\n\n- `max_uses` caps how often that one code can be redeemed; `1` makes it single-use.\n- `expires_in_days` counts from the moment the code is issued, so every\n recipient gets the same window whenever the message goes out. The discount's\n own `ends_at` still applies when it is earlier.\n- `email` restricts the code to a checkout with that email address. A\n restricted code is issued one at a time (`count: 1`).\n\nCodes are uppercase: the prefix is uppercased and followed by 10 characters\nfrom `A–Z` and `2–9` without look-alikes (`0`, `1`, `I`, `O`). A discount holds\nat most 100,000 issued codes; delete unused ones to issue more. Only a discount\nactivated by code can issue codes.\n\nRequires the `write_discounts` token scope." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: - id: 905 discount_id: 41 code: WELCOME-7KQ2M9XHTA kind: generated max_uses: 1 times_used: 0 expires_at: '2026-11-05T09:00:00.000000Z' email: jane@example.com created_at: '2026-10-06T09:00:00.000000Z' properties: data: type: array example: - id: 905 discount_id: 41 code: WELCOME-7KQ2M9XHTA kind: generated max_uses: 1 times_used: 0 expires_at: '2026-11-05T09:00:00.000000Z' email: jane@example.com created_at: '2026-10-06T09:00:00.000000Z' items: type: object properties: id: type: integer example: 905 discount_id: type: integer example: 41 code: type: string example: WELCOME-7KQ2M9XHTA kind: type: string example: generated max_uses: type: integer example: 1 times_used: type: integer example: 0 expires_at: type: string example: '2026-11-05T09:00:00.000000Z' email: type: string example: jane@example.com created_at: type: string example: '2026-10-06T09:00:00.000000Z' 400: description: 'Body that is not valid JSON' content: application/json: schema: type: object example: message: 'The request body is not valid JSON.' properties: message: type: string example: 'The request body is not valid JSON.' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_discounts scope required for this endpoint.' 404: description: 'Discount belongs to another store or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: 'Automatic discount' content: application/json: schema: type: object example: message: 'Codes can only be issued for a discount activated by code.' properties: message: type: string example: 'Codes can only be issued for a discount activated by code.' 422: description: 'Too many codes on the discount' content: application/json: schema: type: object example: message: 'A discount holds at most 100,000 issued codes; this one already has 99,990.' errors: count: - 'A discount holds at most 100,000 issued codes; this one already has 99,990.' properties: message: type: string example: 'A discount holds at most 100,000 issued codes; this one already has 99,990.' errors: type: object properties: count: type: array example: - 'A discount holds at most 100,000 issued codes; this one already has 99,990.' items: type: string 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts requestBody: required: true content: application/json: schema: type: object properties: count: type: integer description: 'Number of codes, 1–1000.' example: 1 prefix: type: string description: 'Up to 20 letters, digits, `-` or `_`.' example: WELCOME- nullable: true max_uses: type: integer description: 'Redemptions allowed per code; null is unlimited.' example: 1 nullable: true expires_in_days: type: integer description: 'Days from now until each code expires, 1–3650.' example: 30 nullable: true email: type: string description: 'Restrict the code to this checkout email; requires `count` 1.' example: jane@example.com nullable: true required: - count parameters: - in: path name: discount description: 'The discount id.' example: 41 required: true schema: type: integer '/public/v1/discounts/{discount}/codes/{code}': delete: summary: 'Delete an issued discount code' operationId: deleteAnIssuedDiscountCode description: "The code stops applying at once; carts holding it are repriced. A discount's\nown code (`kind: primary`) is changed with `PATCH /discounts/{discount}` and\ncannot be deleted here.\n\nRequires the `write_discounts` token scope." parameters: [] responses: 204: description: Deleted content: text/plain: schema: type: string example: '' 401: description: 'Missing or invalid token' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: 'Token without the required scope' content: application/json: schema: type: object example: message: 'This token does not have the write_discounts scope required for this endpoint.' properties: message: type: string example: 'This token does not have the write_discounts scope required for this endpoint.' 404: description: 'Code belongs to another discount or does not exist' content: application/json: schema: type: object example: message: 'Resource not found.' properties: message: type: string example: 'Resource not found.' 409: description: "The discount's own code" content: application/json: schema: type: object example: message: "A discount's own code cannot be deleted; change it with PATCH /discounts/{discount}." properties: message: type: string example: "A discount's own code cannot be deleted; change it with PATCH /discounts/{discount}." 429: description: 'Rate limit exceeded' content: application/json: schema: type: object example: message: 'Too Many Attempts.' properties: message: type: string example: 'Too Many Attempts.' tags: - Discounts parameters: - in: path name: discount description: 'The discount id.' example: 41 required: true schema: type: integer - in: path name: code description: 'The code id from the code list.' example: 905 required: true schema: type: integer