From 4063a083192bb65773d772ebfa011c44822e8cec Mon Sep 17 00:00:00 2001 From: maxakuru <17409558+maxakuru@users.noreply.github.com> Date: Tue, 14 Jul 2026 23:32:48 +0000 Subject: [PATCH] chore(docs): sync generated API reference and schema tables --- api/batch-create-coupons.html | 136 + api/create-coupon-type.html | 130 + api/create-coupon.html | 157 ++ api/create-order.html | 2 + api/delete-coupon-type.html | 99 + api/delete-coupon.html | 76 + api/get-coupon-type.html | 97 + api/get-coupon.html | 106 + api/list-coupon-types.html | 100 + api/list-coupons.html | 74 + api/nav.html | 16 + api/openapi.json | 4919 +++++++++++++++++++++++---------- api/preview-order.html | 2 + api/update-coupon-type.html | 150 + api/update-coupon.html | 147 + docs/schema-reference.md | 4 + 16 files changed, 4717 insertions(+), 1498 deletions(-) create mode 100644 api/batch-create-coupons.html create mode 100644 api/create-coupon-type.html create mode 100644 api/create-coupon.html create mode 100644 api/delete-coupon-type.html create mode 100644 api/delete-coupon.html create mode 100644 api/get-coupon-type.html create mode 100644 api/get-coupon.html create mode 100644 api/list-coupon-types.html create mode 100644 api/list-coupons.html create mode 100644 api/update-coupon-type.html create mode 100644 api/update-coupon.html diff --git a/api/batch-create-coupons.html b/api/batch-create-coupons.html new file mode 100644 index 0000000..6990d35 --- /dev/null +++ b/api/batch-create-coupons.html @@ -0,0 +1,136 @@ + + + + + Batch-generate coupon codes — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Batch-generate coupon codes

+

POST /{org}/sites/{site}/coupons/batch

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Generates `count` (max 500) unique codes with an optional `prefix`, all referencing the given coupon type.

+

Required permissions: coupons:write

+

Path parameters

+
+ + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
+
+

Request headers

+
+ + + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
Content-TypestringyesMust be `application/json`.
+
+

Request body

+
+ + + + + + + + + +
FieldTypeRequiredDescription
typeIdstringyesCoupon type the generated codes reference.
countintegernoNumber of codes to generate (max 500). Defaults to 1.
prefixstringnoOptional code prefix. Defaults to "CODE".
discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
usageLimitnumber | nullnoTotal redemption limit for every code; null for unlimited.
usesPerCustomernumber | nullnoPer-customer redemption limit for every code; null for unlimited.
expiresAtstringnoExpiry timestamp (ISO 8601) applied to every generated code.
+
+

Response

+

201 The generated code count and code names.

+
+ + + + +
FieldTypeRequiredDescription
countintegeryesNumber of codes generated.
codesstring[]yesThe generated code names.
+
+

400 Missing typeId, or referenced coupon type not found.

+
+ + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code.
messagestringyesHuman-readable error message.
errorsobject[]noPer-field validation failures.
+
+

405 Method not allowed — only POST.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
POST /{org}/sites/{site}/coupons/batch
+
{
+  "typeId": "summer-10",
+  "count": 50,
+  "prefix": "SUMMER"
+}
+
+
+
Response · 201
+
{
+  "count": 2,
+  "codes": [
+    "SUMMER-ABCD1234",
+    "SUMMER-EFGH5678"
+  ]
+}
+
+
+
Response · 400
+
{
+  "code": "validation_failed",
+  "message": "invalid request",
+  "errors": [
+    {
+      "path": "$.typeId",
+      "message": "is required"
+    }
+  ]
+}
+
+
+
Response · 405
+
{
+  "code": "method_not_allowed",
+  "message": "GET not allowed"
+}
+
+
+
+ + + diff --git a/api/create-coupon-type.html b/api/create-coupon-type.html new file mode 100644 index 0000000..72ce2cb --- /dev/null +++ b/api/create-coupon-type.html @@ -0,0 +1,130 @@ + + + + + Create a coupon type — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Create a coupon type

+

POST /{org}/sites/{site}/coupons/types

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Validates and stores a coupon type. `id` and `name` are required, plus exactly one discount shape: a flat `discountType`/`discountValue`, or a "product list coupon" `discountedProducts` array. The two shapes are mutually exclusive, as are `country`/`countries`; included/excluded products and categories may not overlap.

+

Required permissions: coupons:write

+

Path parameters

+
+ + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
+
+

Request headers

+
+ + + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
Content-TypestringyesMust be `application/json`.
+
+

Response

+

201 The created coupon type.

+

400 Validation failed (missing/invalid fields, mutually exclusive fields, category overlap, duplicate discountedProducts).

+
+ + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code.
messagestringyesHuman-readable error message.
errorsobject[]noPer-field validation failures.
+
+

409 A coupon type with this id already exists.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
POST /{org}/sites/{site}/coupons/types
+
{
+  "id": "summer-10",
+  "name": "10% Off Summer",
+  "discountType": "percentage",
+  "discountValue": 10,
+  "minimumOrderAmount": 50,
+  "maximumDiscountAmount": 100,
+  "freeShipping": false,
+  "stackable": true
+}
+
+
+
Response · 201
+
{
+  "id": "summer-10",
+  "name": "10% Off Summer",
+  "discountType": "percentage",
+  "discountValue": 10,
+  "minimumOrderAmount": 50,
+  "maximumDiscountAmount": 100,
+  "freeShipping": false,
+  "stackable": true,
+  "createdAt": "2026-01-01T00:00:00.000Z",
+  "updatedAt": "2026-01-01T00:00:00.000Z"
+}
+
+
+
Response · 400
+
{
+  "code": "validation_failed",
+  "message": "invalid request",
+  "errors": [
+    {
+      "path": "$.id",
+      "message": "is required"
+    }
+  ]
+}
+
+
+
Response · 409
+
{
+  "code": "already_exists",
+  "message": "coupon type summer-10 already exists",
+  "resource": "coupon_type",
+  "details": {
+    "typeId": "summer-10"
+  }
+}
+
+
+
+ + + diff --git a/api/create-coupon.html b/api/create-coupon.html new file mode 100644 index 0000000..4259024 --- /dev/null +++ b/api/create-coupon.html @@ -0,0 +1,157 @@ + + + + + Create a coupon code — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Create a coupon code

+

POST /{org}/sites/{site}/coupons

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Creates a single coupon code referencing an existing coupon type. A `discountOverride` is rejected when the referenced type is a product-list coupon.

+

Required permissions: coupons:write

+

Path parameters

+
+ + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
+
+

Request headers

+
+ + + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
Content-TypestringyesMust be `application/json`.
+
+

Request body

+
+ + + + + + + + + + + + +
FieldTypeRequiredDescription
codestringyesThe coupon code (case-insensitive; normalized to uppercase). Letters, digits, hyphens, underscores; max 64 chars.
typeIdstringyesIdentifier of the coupon type this code draws its discount from.
discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
usageLimitnumber | nullnoTotal redemption limit; null for unlimited.
usageCountintegernoTimes redeemed. Managed by the service; ignored on write.
usesPerCustomernumber | nullnoPer-customer redemption limit; null for unlimited.
expiresAtstringnoExpiry timestamp (ISO 8601). Omit for a code that never expires.
activebooleannoWhether the code can be redeemed. Defaults to true.
createdAtstringnoCreation timestamp (ISO 8601). Managed by the service.
updatedAtstringnoLast-update timestamp (ISO 8601). Managed by the service.
+
+

Response

+

201 The created coupon code.

+
+ + + + + + + + + + + + +
FieldTypeRequiredDescription
codestringyesThe coupon code (case-insensitive; normalized to uppercase). Letters, digits, hyphens, underscores; max 64 chars.
typeIdstringyesIdentifier of the coupon type this code draws its discount from.
discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
usageLimitnumber | nullnoTotal redemption limit; null for unlimited.
usageCountintegernoTimes redeemed. Managed by the service; ignored on write.
usesPerCustomernumber | nullnoPer-customer redemption limit; null for unlimited.
expiresAtstringnoExpiry timestamp (ISO 8601). Omit for a code that never expires.
activebooleannoWhether the code can be redeemed. Defaults to true.
createdAtstringnoCreation timestamp (ISO 8601). Managed by the service.
updatedAtstringnoLast-update timestamp (ISO 8601). Managed by the service.
+
+

400 Missing code/typeId, invalid code format, referenced coupon type not found, or a discountOverride on a product-list type.

+
+ + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code.
messagestringyesHuman-readable error message.
errorsobject[]noPer-field validation failures.
+
+

409 A coupon with this code already exists.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
POST /{org}/sites/{site}/coupons
+
{
+  "code": "SAVE10",
+  "typeId": "summer-10",
+  "expiresAt": "2027-01-01T00:00:00Z"
+}
+
+
+
Response · 201
+
{
+  "code": "SAVE10",
+  "typeId": "summer-10",
+  "expiresAt": "2027-01-01T00:00:00Z",
+  "discountOverride": null,
+  "usageLimit": null,
+  "usageCount": 0,
+  "usesPerCustomer": null,
+  "active": true,
+  "createdAt": "2026-01-01T00:00:00.000Z",
+  "updatedAt": "2026-01-01T00:00:00.000Z"
+}
+
+
+
Response · 400
+
{
+  "code": "validation_failed",
+  "message": "invalid request",
+  "errors": [
+    {
+      "path": "$",
+      "message": "code and typeId are required"
+    }
+  ]
+}
+
+
+
Response · 409
+
{
+  "code": "already_exists",
+  "message": "coupon SAVE10 already exists",
+  "resource": "coupon",
+  "details": {
+    "code": "SAVE10",
+    "typeId": "summer-10"
+  }
+}
+
+
+
+ + + diff --git a/api/create-order.html b/api/create-order.html index 4406d52..651fa2f 100644 --- a/api/create-order.html +++ b/api/create-order.html @@ -61,6 +61,8 @@

Request body

shippingMethodobjectno estimateTokenstringno paymentMethodstringno + checkoutFlow"standard" | "express"noCheckout flow type. `express` identifies wallet or shortcut checkout flows. + entryPoint"cart" | "checkout" | "pdp"noPage or experience where checkout started. couponCodestringno giftMessagestringno customerTimezonestringno diff --git a/api/delete-coupon-type.html b/api/delete-coupon-type.html new file mode 100644 index 0000000..d3b906d --- /dev/null +++ b/api/delete-coupon-type.html @@ -0,0 +1,99 @@ + + + + + Delete a coupon type — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Delete a coupon type

+

DELETE /{org}/sites/{site}/coupons/types/{typeId}

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Deletes the coupon type. Blocked with 409 if any codes still reference it.

+

Required permissions: coupons:write

+

Path parameters

+
+ + + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
typeIdstringyesCoupon type identifier.
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

204 Coupon type deleted (no content).

+

404 No coupon type with this id.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+

409 Coupon codes still reference this type.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
Response · 404
+
{
+  "code": "not_found",
+  "message": "coupon type not found",
+  "resource": "coupon_type"
+}
+
+
+
Response · 409
+
{
+  "code": "has_dependents",
+  "message": "coupon type has 3 dependents",
+  "resource": "coupon_type",
+  "details": {
+    "count": 3
+  }
+}
+
+
+
+ + + diff --git a/api/delete-coupon.html b/api/delete-coupon.html new file mode 100644 index 0000000..9dde9e5 --- /dev/null +++ b/api/delete-coupon.html @@ -0,0 +1,76 @@ + + + + + Delete a coupon code — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Delete a coupon code

+

DELETE /{org}/sites/{site}/coupons/{code}

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Required permissions: coupons:write

+

Path parameters

+
+ + + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
codestringyesCoupon code (case-insensitive; normalized to uppercase).
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

204 Coupon deleted (no content).

+

404 No coupon with this code.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
Response · 404
+
{
+  "code": "not_found",
+  "message": "coupon not found",
+  "resource": "coupon"
+}
+
+
+
+ + + diff --git a/api/get-coupon-type.html b/api/get-coupon-type.html new file mode 100644 index 0000000..8e96952 --- /dev/null +++ b/api/get-coupon-type.html @@ -0,0 +1,97 @@ + + + + + Retrieve a coupon type — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Retrieve a coupon type

+

GET /{org}/sites/{site}/coupons/types/{typeId}

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Required permissions: coupons:read

+

Path parameters

+
+ + + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
typeIdstringyesCoupon type identifier.
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

200 The coupon type object.

+

404 No coupon type with this id.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
Response · 200
+
{
+  "id": "bundle-deal",
+  "name": "Bundle Deal",
+  "discountedProducts": [
+    {
+      "path": "/products/widget",
+      "price": "19.99"
+    },
+    {
+      "path": "/products/gadget",
+      "sku": "GADGET-L",
+      "price": "9.99"
+    }
+  ],
+  "stackable": true,
+  "createdAt": "2026-01-01T00:00:00.000Z",
+  "updatedAt": "2026-01-01T00:00:00.000Z"
+}
+
+
+
Response · 404
+
{
+  "code": "not_found",
+  "message": "coupon type not found",
+  "resource": "coupon_type"
+}
+
+
+
+ + + diff --git a/api/get-coupon.html b/api/get-coupon.html new file mode 100644 index 0000000..5446f96 --- /dev/null +++ b/api/get-coupon.html @@ -0,0 +1,106 @@ + + + + + Retrieve a coupon code — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

Retrieve a coupon code

+

GET /{org}/sites/{site}/coupons/{code}

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Required permissions: coupons:read

+

Path parameters

+
+ + + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
codestringyesCoupon code (case-insensitive; normalized to uppercase).
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

200 The coupon code object.

+
+ + + + + + + + + + + + +
FieldTypeRequiredDescription
codestringyesThe coupon code (case-insensitive; normalized to uppercase). Letters, digits, hyphens, underscores; max 64 chars.
typeIdstringyesIdentifier of the coupon type this code draws its discount from.
discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
usageLimitnumber | nullnoTotal redemption limit; null for unlimited.
usageCountintegernoTimes redeemed. Managed by the service; ignored on write.
usesPerCustomernumber | nullnoPer-customer redemption limit; null for unlimited.
expiresAtstringnoExpiry timestamp (ISO 8601). Omit for a code that never expires.
activebooleannoWhether the code can be redeemed. Defaults to true.
createdAtstringnoCreation timestamp (ISO 8601). Managed by the service.
updatedAtstringnoLast-update timestamp (ISO 8601). Managed by the service.
+
+

404 No coupon with this code.

+
+ + + + + + + +
FieldTypeRequiredDescription
codestringyesMachine-readable error code (also sent as the `x-error-code` header).
messagestringyesHuman-readable error message (also sent as the `x-error` header).
resourcestringnoThe resource type involved, when applicable.
retryablebooleannoWhether the caller may retry the request.
detailsobjectnoOptional structured detail.
+
+
+
+
+
Response · 200
+
{
+  "code": "SAVE10",
+  "typeId": "summer-10",
+  "expiresAt": "2027-01-01T00:00:00Z",
+  "discountOverride": null,
+  "usageLimit": null,
+  "usageCount": 0,
+  "usesPerCustomer": null,
+  "active": true,
+  "createdAt": "2026-01-01T00:00:00.000Z",
+  "updatedAt": "2026-01-01T00:00:00.000Z"
+}
+
+
+
Response · 404
+
{
+  "code": "not_found",
+  "message": "coupon not found",
+  "resource": "coupon"
+}
+
+
+
+ + + diff --git a/api/list-coupon-types.html b/api/list-coupon-types.html new file mode 100644 index 0000000..5b0ab76 --- /dev/null +++ b/api/list-coupon-types.html @@ -0,0 +1,100 @@ + + + + + List coupon types — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

List coupon types

+

GET /{org}/sites/{site}/coupons/types

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Returns all coupon type objects for the org/site.

+

Required permissions: coupons:read

+

Path parameters

+
+ + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

200 List of coupon type objects.

+
+ + + +
FieldTypeRequiredDescription
typesobject[]yesCoupon type objects — each a FlatCouponType or a ProductListCouponType.
+
+
+
+
+
Response · 200
+
{
+  "types": [
+    {
+      "id": "summer-10",
+      "name": "10% Off Summer",
+      "discountType": "percentage",
+      "discountValue": 10,
+      "minimumOrderAmount": 50,
+      "maximumDiscountAmount": 100,
+      "freeShipping": false,
+      "stackable": true,
+      "createdAt": "2026-01-01T00:00:00.000Z",
+      "updatedAt": "2026-01-01T00:00:00.000Z"
+    },
+    {
+      "id": "bundle-deal",
+      "name": "Bundle Deal",
+      "discountedProducts": [
+        {
+          "path": "/products/widget",
+          "price": "19.99"
+        },
+        {
+          "path": "/products/gadget",
+          "sku": "GADGET-L",
+          "price": "9.99"
+        }
+      ],
+      "stackable": true,
+      "createdAt": "2026-01-01T00:00:00.000Z",
+      "updatedAt": "2026-01-01T00:00:00.000Z"
+    }
+  ]
+}
+
+
+
+ + + diff --git a/api/list-coupons.html b/api/list-coupons.html new file mode 100644 index 0000000..34984f7 --- /dev/null +++ b/api/list-coupons.html @@ -0,0 +1,74 @@ + + + + + List coupon codes — Helix Commerce API + + + + + + + + + + + +
+
+
+

Coupons

+

List coupon codes

+

GET /{org}/sites/{site}/coupons

+

Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

+

Returns coupon code names, optionally filtered by `type` and/or `active`, with cursor-based pagination.

+

Required permissions: coupons:read

+

Path parameters

+
+ + + + +
NameTypeRequiredDescription
orgstringyesOrganization identifier.
sitestringyesSite identifier.
+
+

Request headers

+
+ + + +
NameTypeRequiredDescription
AuthorizationstringyesBearer token. `Bearer <jwt>`.
+
+

Response

+

200 List of coupon code names with an optional pagination cursor.

+
+ + + + +
FieldTypeRequiredDescription
codesstring[]yesCoupon code names.
cursorstring | nullnoOpaque cursor for the next page; null when there are no more.
+
+
+
+
+
Response · 200
+
{
+  "codes": [
+    "SAVE10",
+    "SUMMER-ABCD1234"
+  ],
+  "cursor": null
+}
+
+
+
+ + + diff --git a/api/nav.html b/api/nav.html index 2353dd0..a10956b 100644 --- a/api/nav.html +++ b/api/nav.html @@ -82,6 +82,22 @@
  • POSTLog out and clear the session cookie
  • +
  • + Coupons + +
  • diff --git a/api/openapi.json b/api/openapi.json index 1a70aac..bfacff4 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.1.0", "info": { "title": "Helix Commerce API", - "version": "2.49.1", + "version": "2.52.1", "description": "Catalog, configuration, orders, and auth API for the Helix Product Bus." }, "servers": [ @@ -51,6 +51,10 @@ { "name": "Auth", "description": "Clears the `auth_token` cookie and revokes the token if a valid one is presented (via cookie or bearer header). Always responds 204, even when no/invalid token is presented." + }, + { + "name": "Coupons", + "description": "Retrieve, update, or delete a single coupon type." } ], "paths": { @@ -3940,1751 +3944,3670 @@ "Auth" ] } - } - }, - "components": { - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT" - } }, - "schemas": { - "Config": { - "type": "object", - "properties": { - "allowedOrigins": { - "type": "array", - "items": { - "type": "string", - "pattern": "^https?:\\/\\/[^/?#\\s]+$", - "maxLength": 1024 - } + "/{org}/sites/{site}/coupons": { + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "allowedDeliverySites": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(\\*|[a-zA-Z0-9-]+)--(\\*|[a-zA-Z0-9-]+)--(\\*|[a-zA-Z0-9-]+)$", - "maxLength": 1024 - } + "description": "Organization identifier." + }, + { + "name": "site", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "auth": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } + "description": "Site identifier." + } + ], + "get": { + "operationId": "listCoupons", + "summary": "List coupon codes", + "description": "Returns coupon code names, optionally filtered by `type` and/or `active`, with cursor-based pagination.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" } - }, - "recaptcha": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "bypassOrigins": { - "type": "array", - "items": { - "type": "string", - "pattern": "^https?:\\/\\/[^/?#\\s]+$", - "maxLength": 1024 - } - }, - "bypassDeliverySites": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(\\*|[a-zA-Z0-9-]+)--[a-zA-Z0-9-]+--[a-zA-Z0-9-]+$", - "maxLength": 1024 + } + ], + "responses": { + "200": { + "description": "List of coupon code names with an optional pagination cursor.", + "content": { + "application/json": { + "schema": { + "description": "A page of coupon code names with an optional pagination cursor.", + "type": "object", + "properties": { + "codes": { + "description": "Coupon code names.", + "type": "array", + "items": { + "type": "string" + } + }, + "cursor": { + "description": "Opaque cursor for the next page; null when there are no more.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "codes" + ] + }, + "examples": { + "example": { + "value": { + "codes": [ + "SAVE10", + "SUMMER-ABCD1234" + ], + "cursor": null + } + } } } } + } + }, + "x-permissions": [ + "coupons:read" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + }, + "post": { + "operationId": "createCoupon", + "summary": "Create a coupon code", + "description": "Creates a single coupon code referencing an existing coupon type. A `discountOverride` is rejected when the referenced type is a product-list coupon.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } }, - "emails": { - "type": "object", - "properties": { - "branding": { - "type": "object", - "properties": { - "logoUrl": { - "type": "string", - "pattern": "^https:\\/\\/", - "maxLength": 1024 - }, - "brandColor": { - "type": "string", - "pattern": "^#[0-9a-fA-F]{3,8}$|^[a-zA-Z]+$", - "maxLength": 20 - }, - "supportEmail": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 - }, - "supportPhone": { - "type": "string", - "pattern": "^[^<>]*$", - "maxLength": 50 - }, - "footerAddress": { - "type": "string", - "pattern": "^[^<>]*$", - "maxLength": 500 + { + "name": "Content-Type", + "in": "header", + "required": true, + "description": "Must be `application/json`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "The created coupon code.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponCode" + }, + "examples": { + "example": { + "value": { + "code": "SAVE10", + "typeId": "summer-10", + "expiresAt": "2027-01-01T00:00:00Z", + "discountOverride": null, + "usageLimit": null, + "usageCount": 0, + "usesPerCustomer": null, + "active": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" + } } } - }, - "otp": { - "type": "object", - "properties": { - "sender": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 - }, - "fromName": { - "type": "string", - "maxLength": 100 - }, - "replyTo": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + } + } + }, + "400": { + "description": "Missing code/typeId, invalid code format, referenced coupon type not found, or a discountOverride on a product-list type.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "validation_failed", + "message": "invalid request", + "errors": [ + { + "path": "$", + "message": "code and typeId are required" + } + ] + } } } - }, - "transactional": { - "type": "object", - "properties": { - "sender": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 - }, - "fromName": { - "type": "string", - "maxLength": 100 - }, - "replyTo": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + } + } + }, + "409": { + "description": "A coupon with this code already exists.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "already_exists", + "message": "coupon SAVE10 already exists", + "resource": "coupon", + "details": { + "code": "SAVE10", + "typeId": "summer-10" + } + } } } } } - }, - "experimentalFlags": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - }, - "friendlyId": { - "type": "object", - "properties": { - "characters": { - "type": "string", - "pattern": "^[^/?#&%<> ]+$", - "minLength": 2 - }, - "length": { - "type": "integer", - "minimum": 4, - "maximum": 32 + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "The coupon code to create.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponCode" }, - "prefix": { - "type": "string", - "pattern": "^[^/?#&%<> ]+$", - "minLength": 1, - "maxLength": 8 + "examples": { + "example": { + "value": { + "code": "SAVE10", + "typeId": "summer-10", + "expiresAt": "2027-01-01T00:00:00Z" + } + } } } + } + }, + "tags": [ + "Coupons" + ] + } + }, + "/{org}/sites/{site}/coupons/batch": { + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "geoOverrides": { - "type": "array", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "pattern": "^[a-z]{2}$" - }, - "friendlyId": { + "description": "Organization identifier." + }, + { + "name": "site", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Site identifier." + } + ], + "post": { + "operationId": "batchCreateCoupons", + "summary": "Batch-generate coupon codes", + "description": "Generates `count` (max 500) unique codes with an optional `prefix`, all referencing the given coupon type.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + }, + { + "name": "Content-Type", + "in": "header", + "required": true, + "description": "Must be `application/json`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "The generated code count and code names.", + "content": { + "application/json": { + "schema": { + "description": "The generated code count and names.", "type": "object", "properties": { - "characters": { - "type": "string", - "pattern": "^[^/?#&%<> ]+$", - "minLength": 2 + "count": { + "description": "Number of codes generated.", + "type": "integer" }, - "length": { - "type": "integer", - "minimum": 4, - "maximum": 32 - }, - "prefix": { - "type": "string", - "pattern": "^[^/?#&%<> ]+$", - "minLength": 1, - "maxLength": 8 + "codes": { + "description": "The generated code names.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "count", + "codes" + ] + }, + "examples": { + "example": { + "value": { + "count": 2, + "codes": [ + "SUMMER-ABCD1234", + "SUMMER-EFGH5678" + ] } } + } + } + } + }, + "400": { + "description": "Missing typeId, or referenced coupon type not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" }, - "emails": { - "type": "object", - "properties": { - "branding": { - "type": "object", - "properties": { - "logoUrl": { - "type": "string", - "pattern": "^https:\\/\\/", - "maxLength": 1024 - }, - "brandColor": { - "type": "string", - "pattern": "^#[0-9a-fA-F]{3,8}$|^[a-zA-Z]+$", - "maxLength": 20 - }, - "supportEmail": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 - }, - "supportPhone": { - "type": "string", - "pattern": "^[^<>]*$", - "maxLength": 50 - }, - "footerAddress": { - "type": "string", - "pattern": "^[^<>]*$", - "maxLength": 500 - } - } - }, - "transactional": { - "type": "object", - "properties": { - "sender": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 - }, - "fromName": { - "type": "string", - "maxLength": 100 - }, - "replyTo": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + "examples": { + "example": { + "value": { + "code": "validation_failed", + "message": "invalid request", + "errors": [ + { + "path": "$.typeId", + "message": "is required" } - } + ] } } + } + } + } + }, + "405": { + "description": "Method not allowed — only POST.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" }, - "experimentalFlags": { - "type": "object", - "additionalProperties": { - "type": "boolean" + "examples": { + "example": { + "value": { + "code": "method_not_allowed", + "message": "GET not allowed" + } } } + } + } + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Batch parameters.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BatchCreateCouponsRequest" }, - "required": [ - "country" - ] + "examples": { + "example": { + "value": { + "typeId": "summer-10", + "count": 50, + "prefix": "SUMMER" + } + } + } } } - } - }, - "ProductBus": { - "description": "A Product Bus catalog entry representing a single product or configurable product.", - "type": "object", - "properties": { - "sku": { - "description": "Unique stock-keeping unit identifier.", - "type": "string" - }, - "path": { - "description": "URL path for this product (e.g. \"/products/my-product\").", - "type": "string", - "pattern": "^\\/([a-z0-9_]+([-_][a-z0-9_]+)*\\/)*[a-z0-9]+(-[a-z0-9]+)*$", - "maxLength": 900 - }, - "urlKey": { - "description": "URL key used to construct the canonical path.", - "type": "string" - }, - "description": { - "description": "Full product description.", - "type": "string" - }, - "name": { - "description": "Display name for the product.", - "type": "string" - }, - "metaTitle": { - "description": "HTML meta title override.", - "type": "string" - }, - "metaDescription": { - "description": "HTML meta description override.", - "type": "string" - }, - "gtin": { - "description": "Global Trade Item Number (barcode).", - "type": "string" - }, - "url": { - "description": "Canonical absolute URL for the product.", - "type": "string" - }, - "brand": { - "description": "Brand or manufacturer name.", + }, + "tags": [ + "Coupons" + ] + } + }, + "/{org}/sites/{site}/coupons/{code}": { + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { "type": "string" }, - "type": { - "description": "Product type identifier (e.g. \"simple\", \"configurable\", \"bundle\").", + "description": "Organization identifier." + }, + { + "name": "site", + "in": "path", + "required": true, + "schema": { "type": "string" }, - "availability": { - "description": "schema.org availability status for a product or offer.", - "type": "string", - "enum": [ - "BackOrder", - "Discontinued", - "InStock", - "InStoreOnly", - "LimitedAvailability", - "MadeToOrder", - "OnlineOnly", - "OutOfStock", - "PreOrder", - "PreSale", - "Reserved", - "SoldOut" - ] - }, - "availabilityDate": { - "description": "ISO 8601 date when the product becomes available.", + "description": "Site identifier." + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { "type": "string" }, - "price": { - "description": "Price information for a product or variant.", - "type": "object", - "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" - }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" - }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" - } - } - }, - "itemCondition": { - "description": "schema.org item condition.", - "type": "string", - "enum": [ - "DamagedCondition", - "NewCondition", - "RefurbishedCondition", - "UsedCondition" - ] - }, - "metadata": { - "description": "Arbitrary key/value metadata attached to the product.", - "type": "object", - "additionalProperties": { + "description": "Coupon code (case-insensitive; normalized to uppercase)." + } + ], + "get": { + "operationId": "getCoupon", + "summary": "Retrieve a coupon code", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { "type": "string" } - }, - "options": { - "description": "Configurable options available for this product (e.g. Color, Size).", - "type": "array", - "items": { - "description": "A configurable product option with its available values (e.g. Color, Size).", - "type": "object", - "properties": { - "id": { - "description": "Option identifier, typically matching the attribute code.", - "type": "string" - }, - "label": { - "description": "Display label for the option group (e.g. \"Color\").", - "type": "string" - }, - "position": { - "description": "Sort order for display.", - "type": "number" + } + ], + "responses": { + "200": { + "description": "The coupon code object.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponCode" }, - "values": { - "description": "Available values for this option.", - "type": "array", - "items": { - "description": "A single selectable value for a product option.", - "type": "object", - "properties": { - "id": { - "description": "Unique identifier for this option value.", - "type": "string" - }, - "value": { - "description": "Display label for this option value (e.g. \"Red\", \"Large\").", - "type": "string" - }, - "uid": { - "description": "Internal UID used by some backends.", - "type": "string" - } - }, - "required": [ - "value" - ] + "examples": { + "example": { + "value": { + "code": "SAVE10", + "typeId": "summer-10", + "expiresAt": "2027-01-01T00:00:00Z", + "discountOverride": null, + "usageLimit": null, + "usageCount": 0, + "usesPerCustomer": null, + "active": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" + } } } - }, - "required": [ - "label", - "values" - ] - } - }, - "aggregateRating": { - "description": "Aggregate customer rating for schema.org structured data.", - "type": "object", - "properties": { - "ratingValue": { - "description": "Average rating value. Numeric string; converted to a number in JSON-LD.", - "type": "string" - }, - "reviewCount": { - "description": "Total number of ratings. Numeric string; converted to an integer in JSON-LD.", - "type": "string" - }, - "bestRating": { - "description": "Best possible rating. Numeric string.", - "type": "string" - }, - "worstRating": { - "description": "Worst possible rating. Numeric string.", - "type": "string" } } }, - "images": { - "description": "Product images.", - "type": "array", - "items": { - "description": "Product media asset. An image, or a video when the video field is set.", - "type": "object", - "properties": { - "url": { - "description": "Absolute URL of the image.", - "type": "string" - }, - "label": { - "description": "Accessible alt text for the image.", - "type": "string" - }, - "filename": { - "description": "Original filename of the image.", - "type": "string", - "pattern": "^[A-Za-z0-9_-]+$" + "404": { + "description": "No coupon with this code.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" }, - "roles": { - "description": "Semantic roles assigned to this image, e.g. \"thumbnail\".", - "type": "array", - "items": { - "type": "string" + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon not found", + "resource": "coupon" + } } - }, - "video": { - "description": "Absolute URL of an associated video asset, when this media entry represents a video.", - "type": "string" } - }, - "required": [ - "url" - ] + } } - }, - "variants": { - "description": "Available variants for a configurable product.", - "type": "array", - "items": { - "description": "A purchasable variant of a configurable product.", - "type": "object", - "properties": { - "sku": { - "description": "Unique stock-keeping unit identifier.", - "type": "string" - }, - "name": { - "description": "Display name for this variant.", - "type": "string" - }, - "price": { - "description": "Price information for a product or variant.", - "type": "object", - "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" - }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" - }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" - } - } - }, - "url": { - "description": "Canonical URL for this variant.", - "type": "string" - }, - "images": { - "description": "Images for this variant.", - "type": "array", - "items": { - "description": "Product media asset. An image, or a video when the video field is set.", - "type": "object", - "properties": { - "url": { - "description": "Absolute URL of the image.", - "type": "string" - }, - "label": { - "description": "Accessible alt text for the image.", - "type": "string" - }, - "filename": { - "description": "Original filename of the image.", - "type": "string", - "pattern": "^[A-Za-z0-9_-]+$" - }, - "roles": { - "description": "Semantic roles assigned to this image, e.g. \"thumbnail\".", - "type": "array", - "items": { - "type": "string" - } - }, - "video": { - "description": "Absolute URL of an associated video asset, when this media entry represents a video.", - "type": "string" - } - }, - "required": [ - "url" - ] - } - }, - "gtin": { - "description": "Global Trade Item Number (barcode).", - "type": "string" - }, - "description": { - "description": "Variant-specific description.", - "type": "string" - }, - "availability": { - "description": "schema.org availability status for a product or offer.", - "type": "string", - "enum": [ - "BackOrder", - "Discontinued", - "InStock", - "InStoreOnly", - "LimitedAvailability", - "MadeToOrder", - "OnlineOnly", - "OutOfStock", - "PreOrder", - "PreSale", - "Reserved", - "SoldOut" - ] - }, - "options": { - "description": "Option values that identify this variant (e.g. color=Red, size=Large).", - "type": "array", - "items": { - "description": "A single selectable value for a product option.", - "type": "object", - "properties": { - "id": { - "description": "Unique identifier for this option value.", - "type": "string" - }, - "value": { - "description": "Display label for this option value (e.g. \"Red\", \"Large\").", - "type": "string" - }, - "uid": { - "description": "Internal UID used by some backends.", - "type": "string" - } - }, - "required": [ - "value" - ] - } - }, - "itemCondition": { - "description": "schema.org item condition.", - "type": "string", - "enum": [ - "DamagedCondition", - "NewCondition", - "RefurbishedCondition", - "UsedCondition" - ] - }, - "custom": { - "type": "object", - "additionalProperties": true - }, - "jsonldExtensions": { - "description": "Additional schema.org properties shallow-merged into this variant's Offer in the auto-generated JSON-LD. Max 16,000 characters when serialized.", - "type": "object", - "additionalProperties": true + } + }, + "x-permissions": [ + "coupons:read" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + }, + "put": { + "operationId": "updateCoupon", + "summary": "Update a coupon code", + "description": "Merges the request body into the existing coupon. `code`, `typeId`, `usageCount`, and `createdAt` are immutable. A `discountOverride` is rejected when the referenced type is a product-list coupon.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + }, + { + "name": "Content-Type", + "in": "header", + "required": true, + "description": "Must be `application/json`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The updated coupon code.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponCode" }, - "weight": { - "description": "Product weight for display and JSON-LD structured data.", - "type": "object", - "properties": { + "examples": { + "example": { "value": { - "description": "Numeric weight value.", - "type": "number" - }, - "unit": { - "description": "Unit of weight measurement.", - "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + "code": "SAVE10", + "typeId": "summer-10", + "expiresAt": "2027-01-01T00:00:00Z", + "discountOverride": null, + "usageLimit": null, + "usageCount": 0, + "usesPerCustomer": null, + "active": false, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" } - }, - "required": [ - "value", - "unit" - ] + } + } + } + } + }, + "400": { + "description": "A discountOverride was set on a code of a product-list coupon type.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" }, - "shippingDimensions": { - "description": "Physical dimensions used for shipping rate calculation.", - "type": "object", - "properties": { - "weight": { - "description": "Product weight for display and JSON-LD structured data.", - "type": "object", - "properties": { - "value": { - "description": "Numeric weight value.", - "type": "number" - }, - "unit": { - "description": "Unit of weight measurement.", - "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + "examples": { + "example": { + "value": { + "code": "validation_failed", + "message": "invalid request", + "errors": [ + { + "path": "$.discountOverride", + "message": "not allowed for a product-list coupon type" } - }, - "required": [ - "value", - "unit" - ] - }, - "height": { - "description": "Height in the declared dimensionsUnit.", - "type": "number" - }, - "width": { - "description": "Width in the declared dimensionsUnit.", - "type": "number" - }, - "depth": { - "description": "Depth in the declared dimensionsUnit.", - "type": "number" - }, - "dimensionsUnit": { - "description": "Unit of dimension measurement.", - "type": "string", - "enum": [ - "cm", - "mm", - "in" ] } } } - }, - "required": [ - "sku", - "name", - "url", - "images" - ] + } } }, - "jsonld": { - "description": "Full JSON-LD override. When present, replaces the auto-generated structured data.", - "type": "string", - "maxLength": 128000 - }, - "custom": { - "type": "object", - "additionalProperties": true - }, - "jsonldExtensions": { - "description": "Additional schema.org properties shallow-merged into the auto-generated Product JSON-LD object. Ignored when jsonld override is used. Max 32,000 characters when serialized.", - "type": "object", - "additionalProperties": true - }, - "shipping": { - "anyOf": [ - { - "type": "string" - }, - { - "description": "A single shipping option in Google Merchant Center format.", - "type": "object", - "properties": { - "country": { - "description": "Two-letter country code (ISO 3166-1 alpha-2).", - "type": "string" - }, - "region": { - "description": "State or region code.", - "type": "string" - }, - "service": { - "description": "Shipping service label (e.g. \"Standard\", \"Overnight\").", - "type": "string" - }, - "price": { - "description": "Shipping cost with currency code (e.g. \"16.00 USD\").", - "type": "string" - }, - "min_handling_time": { - "description": "Minimum order handling time in business days.", - "type": "string" - }, - "max_handling_time": { - "description": "Maximum order handling time in business days.", - "type": "string" - }, - "min_transit_time": { - "description": "Minimum shipping transit time in business days.", - "type": "string" - }, - "max_transit_time": { - "description": "Maximum shipping transit time in business days.", - "type": "string" + "404": { + "description": "No coupon with this code.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon not found", + "resource": "coupon" + } } } + } + } + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Partial coupon code fields to merge into the existing code.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponCodeUpdate" }, - { - "type": "array", - "items": { - "description": "A single shipping option in Google Merchant Center format.", - "type": "object", - "properties": { - "country": { - "description": "Two-letter country code (ISO 3166-1 alpha-2).", - "type": "string" - }, - "region": { - "description": "State or region code.", - "type": "string" - }, - "service": { - "description": "Shipping service label (e.g. \"Standard\", \"Overnight\").", - "type": "string" - }, - "price": { - "description": "Shipping cost with currency code (e.g. \"16.00 USD\").", - "type": "string" - }, - "min_handling_time": { - "description": "Minimum order handling time in business days.", - "type": "string" - }, - "max_handling_time": { - "description": "Maximum order handling time in business days.", - "type": "string" - }, - "min_transit_time": { - "description": "Minimum shipping transit time in business days.", - "type": "string" - }, - "max_transit_time": { - "description": "Maximum shipping transit time in business days.", - "type": "string" - } + "examples": { + "example": { + "value": { + "active": false } } } - ] + } + } + }, + "tags": [ + "Coupons" + ] + }, + "delete": { + "operationId": "deleteCoupon", + "summary": "Delete a coupon code", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Coupon deleted (no content)." }, - "bundleItems": { - "description": "Bundle composition. Presence of this array (regardless of contents) marks this product as a bundle.", - "type": "array", - "items": { - "description": "One entry in a bundle product's composition. May be a simple item (sku + price) or a configurable item (variants array). Presence of the parent product's bundleItems array marks it as a bundle.", - "type": "object", - "properties": { - "sku": { - "description": "SKU for a simple bundle item.", - "type": "string" - }, - "name": { - "description": "Display name for a simple bundle item.", - "type": "string" + "404": { + "description": "No coupon with this code.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" }, - "price": { - "description": "Price for a bundle component. Narrower than ProductBusPrice -- no currency field (currency comes from the parent line item).", + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon not found", + "resource": "coupon" + } + } + } + } + } + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + } + }, + "/{org}/sites/{site}/coupons/types": { + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization identifier." + }, + { + "name": "site", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Site identifier." + } + ], + "get": { + "operationId": "listCouponTypes", + "summary": "List coupon types", + "description": "Returns all coupon type objects for the org/site.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of coupon type objects.", + "content": { + "application/json": { + "schema": { + "description": "A list of coupon type objects.", "type": "object", "properties": { - "final": { - "description": "Component price as a decimal string.", - "type": "string" - }, - "regular": { - "description": "Pre-discount price for display purposes.", - "type": "string" + "types": { + "description": "Coupon type objects — each a FlatCouponType or a ProductListCouponType.", + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } } }, "required": [ - "final" + "types" ] }, - "variants": { - "description": "Variants for a configurable bundle item. When present, the server selects one variant at preview time.", - "type": "array", - "items": { - "description": "One variant of a configurable bundle item. The server selects the variant whose options are all satisfied by the parent line item's selectedOptions.", - "type": "object", - "properties": { - "sku": { - "description": "SKU for this variant.", - "type": "string" - }, - "name": { - "description": "Display name for this variant.", - "type": "string" - }, - "price": { - "description": "Price for a bundle component. Narrower than ProductBusPrice -- no currency field (currency comes from the parent line item).", - "type": "object", - "properties": { - "final": { - "description": "Component price as a decimal string.", - "type": "string" - }, - "regular": { - "description": "Pre-discount price for display purposes.", - "type": "string" - } + "examples": { + "example": { + "value": { + "types": [ + { + "id": "summer-10", + "name": "10% Off Summer", + "discountType": "percentage", + "discountValue": 10, + "minimumOrderAmount": 50, + "maximumDiscountAmount": 100, + "freeShipping": false, + "stackable": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" }, - "required": [ - "final" - ] - }, - "options": { - "description": "Option pairs that identify this variant.", - "type": "array", - "items": { - "description": "Option pair on a configurable bundle item variant. The server resolves which variant to ship by matching every entry here against the parent line item's selectedOptions.", - "type": "object", - "properties": { - "id": { - "description": "Option identifier, matched against selectedOptions[].id.", - "type": "string" + { + "id": "bundle-deal", + "name": "Bundle Deal", + "discountedProducts": [ + { + "path": "/products/widget", + "price": "19.99" }, - "name": { - "description": "Option value label, matched against selectedOptions[].value.", - "type": "string" + { + "path": "/products/gadget", + "sku": "GADGET-L", + "price": "9.99" } - }, - "required": [ - "id", - "name" - ] + ], + "stackable": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" } - }, - "taxCode": { - "description": "Per-variant tax classification code. Falls back to the bundle parent's taxCode when absent.", - "type": "string", - "maxLength": 255 - }, - "taxData": { - "description": "Supplementary tax data. Falls back to the bundle parent's taxData when absent.", - "type": "object", - "additionalProperties": true - } - }, - "required": [ - "sku", - "price", - "options" - ] + ] + } } - }, - "taxCode": { - "description": "Per-component tax classification code. Falls back to the bundle parent's taxCode when absent.", - "type": "string", - "maxLength": 255 - }, - "taxData": { - "description": "Supplementary tax data. Falls back to the bundle parent's taxData when absent.", - "type": "object", - "additionalProperties": true } } } + } + }, + "x-permissions": [ + "coupons:read" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + }, + "post": { + "operationId": "createCouponType", + "summary": "Create a coupon type", + "description": "Validates and stores a coupon type. `id` and `name` are required, plus exactly one discount shape: a flat `discountType`/`discountValue`, or a \"product list coupon\" `discountedProducts` array. The two shapes are mutually exclusive, as are `country`/`countries`; included/excluded products and categories may not overlap.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } }, - "feeds": { - "description": "Feed configuration for product distribution.", - "type": "object", - "properties": { - "common": { - "description": "Common feed settings shared across product distribution channels.", - "type": "object", - "properties": { - "geoTargetCountries": { - "description": "Target countries for product feeds.", - "type": "array", - "items": { - "type": "string" + { + "name": "Content-Type", + "in": "header", + "required": true, + "description": "Must be `application/json`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "The created coupon type.", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/FlatCouponType" + }, + { + "$ref": "#/components/schemas/ProductListCouponType" + } + ] + }, + "examples": { + "example": { + "value": { + "id": "summer-10", + "name": "10% Off Summer", + "discountType": "percentage", + "discountValue": 10, + "minimumOrderAmount": 50, + "maximumDiscountAmount": 100, + "freeShipping": false, + "stackable": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" } - }, - "geoStoreCountry": { - "description": "Store country for feed generation.", - "type": "string" } } - }, - "oai": { - "description": "Product feed eligibility for the OpenAI / agentic commerce feed.", - "type": "object", - "properties": { - "isEligibleForSearch": { - "description": "Whether the product is eligible for search feeds.", - "type": "boolean" - }, - "isEligibleForCheckout": { - "description": "Whether the product supports checkout via feeds.", - "type": "boolean" - } - }, - "required": [ - "isEligibleForSearch", - "isEligibleForCheckout" - ] } } }, - "weight": { - "description": "Product weight for display and JSON-LD structured data.", - "type": "object", - "properties": { - "value": { - "description": "Numeric weight value.", - "type": "number" - }, - "unit": { - "description": "Unit of weight measurement.", - "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + "400": { + "description": "Validation failed (missing/invalid fields, mutually exclusive fields, category overlap, duplicate discountedProducts).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "validation_failed", + "message": "invalid request", + "errors": [ + { + "path": "$.id", + "message": "is required" + } + ] + } + } + } } - }, - "required": [ - "value", - "unit" - ] + } }, - "shippingDimensions": { - "description": "Physical dimensions used for shipping rate calculation.", - "type": "object", - "properties": { - "weight": { - "description": "Product weight for display and JSON-LD structured data.", - "type": "object", - "properties": { - "value": { - "description": "Numeric weight value.", - "type": "number" + "409": { + "description": "A coupon type with this id already exists.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "already_exists", + "message": "coupon type summer-10 already exists", + "resource": "coupon_type", + "details": { + "typeId": "summer-10" + } + } + } + } + } + } + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "The coupon type to create — either a flat or a product-list coupon.", + "required": true, + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/FlatCouponType" }, - "unit": { - "description": "Unit of weight measurement.", - "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + { + "$ref": "#/components/schemas/ProductListCouponType" } - }, - "required": [ - "value", - "unit" ] }, - "height": { - "description": "Height in the declared dimensionsUnit.", - "type": "number" - }, - "width": { - "description": "Width in the declared dimensionsUnit.", - "type": "number" - }, - "depth": { - "description": "Depth in the declared dimensionsUnit.", - "type": "number" - }, - "dimensionsUnit": { - "description": "Unit of dimension measurement.", - "type": "string", - "enum": [ - "cm", - "mm", - "in" - ] + "examples": { + "example": { + "value": { + "id": "summer-10", + "name": "10% Off Summer", + "discountType": "percentage", + "discountValue": 10, + "minimumOrderAmount": 50, + "maximumDiscountAmount": 100, + "freeShipping": false, + "stackable": true + } + } } } - }, - "taxCode": { - "description": "Tax classification code for this product.", - "type": "string", - "maxLength": 255 - }, - "taxData": { - "description": "Supplementary tax data passed to the tax provider.", - "type": "object", - "additionalProperties": true - }, - "country": { - "description": "ISO 3166-1 alpha-2 store country code.", - "type": "string", - "pattern": "^[a-z]{2}$" - }, - "locale": { - "description": "BCP-47 locale tag for this product entry.", - "type": "string", - "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" } }, - "required": [ - "sku", - "name", - "path" + "tags": [ + "Coupons" ] - }, - "Order": { - "type": "object", - "properties": { - "customer": { - "$ref": "#/components/schemas/Customer" + } + }, + "/{org}/sites/{site}/coupons/types/{typeId}": { + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "shipping": { - "$ref": "#/components/schemas/Address" + "description": "Organization identifier." + }, + { + "name": "site", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "billing": { - "$ref": "#/components/schemas/Address" + "description": "Site identifier." + }, + { + "name": "typeId", + "in": "path", + "required": true, + "schema": { + "type": "string" }, - "items": { - "type": "array", - "items": { - "description": "A single line item in an order or estimate.", - "type": "object", - "properties": { - "name": { - "description": "Display name for this line item.", - "type": "string" - }, - "note": { - "description": "Optional customer note for this line item.", - "type": "string" - }, - "sku": { - "description": "SKU of the product.", - "type": "string" - }, - "path": { - "description": "Product page path.", - "type": "string" - }, - "imageUrl": { - "description": "Product image URL for order confirmation display.", - "type": "string" - }, - "productUrl": { - "description": "Canonical product URL.", - "type": "string" - }, - "quantity": { - "description": "Quantity ordered. Must be a whole number from 1 to 1000.", - "type": "integer", - "minimum": 1, - "maximum": 1000 - }, - "price": { - "description": "Price information for a product or variant.", - "type": "object", - "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" - }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" + "description": "Coupon type identifier." + } + ], + "get": { + "operationId": "getCouponType", + "summary": "Retrieve a coupon type", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The coupon type object.", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/FlatCouponType" }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" + { + "$ref": "#/components/schemas/ProductListCouponType" } - } + ] }, - "shippingDimensions": { - "description": "Physical dimensions used for shipping rate calculation.", - "type": "object", - "properties": { - "weight": { - "description": "Product weight for display and JSON-LD structured data.", - "type": "object", - "properties": { - "value": { - "description": "Numeric weight value.", - "type": "number" + "examples": { + "example": { + "value": { + "id": "bundle-deal", + "name": "Bundle Deal", + "discountedProducts": [ + { + "path": "/products/widget", + "price": "19.99" }, - "unit": { - "description": "Unit of weight measurement.", - "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + { + "path": "/products/gadget", + "sku": "GADGET-L", + "price": "9.99" } - }, - "required": [ - "value", - "unit" - ] - }, - "height": { - "description": "Height in the declared dimensionsUnit.", - "type": "number" - }, - "width": { - "description": "Width in the declared dimensionsUnit.", - "type": "number" - }, - "depth": { - "description": "Depth in the declared dimensionsUnit.", - "type": "number" - }, - "dimensionsUnit": { - "description": "Unit of dimension measurement.", - "type": "string", - "enum": [ - "cm", - "mm", - "in" - ] + ], + "stackable": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" } } + } + } + } + }, + "404": { + "description": "No coupon type with this id.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" }, - "selectedOptions": { - "description": "Option values selected by the customer.", - "type": "array", - "items": { - "description": "A customer-selected option value for a line item (e.g. color=Red).", - "type": "object", - "properties": { - "id": { - "description": "Option identifier.", - "type": "string" - }, - "value": { - "description": "Selected value.", - "type": "string" - } - }, - "required": [ - "id", - "value" - ] + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon type not found", + "resource": "coupon_type" + } } - }, - "bundleItems": { - "description": "Resolved bundle component line items nested on a bundle parent. Not counted toward the order subtotal -- the parent price is the chargeable value.", - "type": "array", - "items": { - "description": "A resolved bundle component line item nested on a bundle parent order item.", - "type": "object", - "properties": { - "name": { - "description": "Display name of the component.", - "type": "string" - }, - "sku": { - "description": "SKU of the component.", - "type": "string" - }, - "path": { - "description": "Product page path of the component.", - "type": "string" - }, - "quantity": { - "description": "Quantity ordered. Must be a whole number from 1 to 1000.", - "type": "integer", - "minimum": 1, - "maximum": 1000 - }, - "price": { - "description": "Price information for a product or variant.", - "type": "object", - "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" - }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" - }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" - } - } - } + } + } + } + } + }, + "x-permissions": [ + "coupons:read" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + }, + "put": { + "operationId": "updateCouponType", + "summary": "Update a coupon type", + "description": "Merges the request body into the existing coupon type. `id` and `createdAt` are immutable. Setting `country` clears `countries` (and vice versa); switching between the flat and product-list shapes clears the opposing fields. Switching to the flat shape requires both `discountType` and `discountValue`.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + }, + { + "name": "Content-Type", + "in": "header", + "required": true, + "description": "Must be `application/json`.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The updated coupon type.", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/FlatCouponType" }, - "required": [ - "path", - "quantity", - "price" - ] - } + { + "$ref": "#/components/schemas/ProductListCouponType" + } + ] }, - "custom": { - "description": "Arbitrary custom data for this line item.", - "type": "object", - "additionalProperties": true + "examples": { + "example": { + "value": { + "id": "summer-10", + "name": "10% Off Summer", + "discountType": "percentage", + "discountValue": 15, + "minimumOrderAmount": 50, + "maximumDiscountAmount": 100, + "freeShipping": false, + "stackable": true, + "createdAt": "2026-01-01T00:00:00.000Z", + "updatedAt": "2026-01-01T00:00:00.000Z" + } + } } - }, - "required": [ - "sku", - "path", - "quantity", - "price" - ] + } } }, - "country": { - "type": "string", - "pattern": "^[a-z]{2}$" - }, - "locale": { - "type": "string", - "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" - }, - "shippingMethod": { - "type": "object", - "properties": { - "id": { - "type": "string" + "400": { + "description": "Validation failed (mutually exclusive fields, category overlap, invalid country/locale, incomplete flat discount).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "validation_failed", + "message": "invalid request", + "errors": [ + { + "path": "$.country", + "message": "invalid country code" + } + ] + } + } + } } - }, - "required": [ - "id" - ] - }, - "estimateToken": { - "type": "string" - }, - "paymentMethod": { - "type": "string" - }, - "couponCode": { - "type": "string" - }, - "giftMessage": { - "type": "string", - "maxLength": 250 - }, - "customerTimezone": { - "type": "string", - "pattern": "^[A-Za-z0-9_+\\-/]+$", - "maxLength": 100 + } }, - "custom": { - "type": "object", - "additionalProperties": { - "type": "string", - "maxLength": 2048 + "404": { + "description": "No coupon type with this id.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon type not found", + "resource": "coupon_type" + } + } + } + } } } }, - "required": [ - "items", - "customer", - "shipping", - "country", - "locale" + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Partial coupon type fields to merge into the existing type.", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CouponTypeUpdate" + }, + "examples": { + "example": { + "value": { + "discountValue": 15 + } + } + } + } + } + }, + "tags": [ + "Coupons" ] }, - "PreviewOrder": { - "type": "object", - "properties": { - "customer": { - "$ref": "#/components/schemas/Customer" + "delete": { + "operationId": "deleteCouponType", + "summary": "Delete a coupon type", + "description": "Deletes the coupon type. Blocked with 409 if any codes still reference it.", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "Bearer token. `Bearer `.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Coupon type deleted (no content)." }, - "shipping": { - "description": "A shipping or billing address.", - "type": "object", - "properties": { - "name": { - "description": "Full name of the recipient.", - "type": "string", - "maxLength": 255 - }, - "company": { - "description": "Company name.", - "type": "string", - "maxLength": 255 - }, - "address1": { - "description": "Primary street address line.", - "type": "string", - "maxLength": 255 - }, - "address2": { - "description": "Secondary address line (apartment, suite, etc.).", - "type": "string", - "maxLength": 255 - }, - "city": { - "description": "City name.", - "type": "string", - "maxLength": 255 - }, - "state": { - "description": "State or province code.", - "type": "string", - "maxLength": 255 - }, - "zip": { - "description": "Postal or ZIP code.", - "type": "string", - "maxLength": 255 - }, - "country": { - "description": "ISO 3166-1 alpha-2 country code.", - "type": "string", - "maxLength": 255 - }, - "phone": { - "description": "Phone number.", - "type": "string", - "maxLength": 255 + "404": { + "description": "No coupon type with this id.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "not_found", + "message": "coupon type not found", + "resource": "coupon_type" + } + } + } + } + } + }, + "409": { + "description": "Coupon codes still reference this type.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "examples": { + "example": { + "value": { + "code": "has_dependents", + "message": "coupon type has 3 dependents", + "resource": "coupon_type", + "details": { + "count": 3 + } + } + } + } + } + } + } + }, + "x-permissions": [ + "coupons:write" + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "Coupons" + ] + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + }, + "schemas": { + "Config": { + "type": "object", + "properties": { + "allowedOrigins": { + "type": "array", + "items": { + "type": "string", + "pattern": "^https?:\\/\\/[^/?#\\s]+$", + "maxLength": 1024 + } + }, + "allowedDeliverySites": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(\\*|[a-zA-Z0-9-]+)--(\\*|[a-zA-Z0-9-]+)--(\\*|[a-zA-Z0-9-]+)$", + "maxLength": 1024 + } + }, + "auth": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "recaptcha": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" }, - "email": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + "bypassOrigins": { + "type": "array", + "items": { + "type": "string", + "pattern": "^https?:\\/\\/[^/?#\\s]+$", + "maxLength": 1024 + } }, - "isDefault": { - "description": "Whether this is the default address for the customer.", - "type": "boolean" + "bypassDeliverySites": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(\\*|[a-zA-Z0-9-]+)--[a-zA-Z0-9-]+--[a-zA-Z0-9-]+$", + "maxLength": 1024 + } + } + } + }, + "emails": { + "type": "object", + "properties": { + "branding": { + "type": "object", + "properties": { + "logoUrl": { + "type": "string", + "pattern": "^https:\\/\\/", + "maxLength": 1024 + }, + "brandColor": { + "type": "string", + "pattern": "^#[0-9a-fA-F]{3,8}$|^[a-zA-Z]+$", + "maxLength": 20 + }, + "supportEmail": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "supportPhone": { + "type": "string", + "pattern": "^[^<>]*$", + "maxLength": 50 + }, + "footerAddress": { + "type": "string", + "pattern": "^[^<>]*$", + "maxLength": 500 + } + } }, - "isValidated": { - "description": "Whether this address has been validated by an address verification service.", - "type": "boolean" + "otp": { + "type": "object", + "properties": { + "sender": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "fromName": { + "type": "string", + "maxLength": 100 + }, + "replyTo": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + } + } + }, + "transactional": { + "type": "object", + "properties": { + "sender": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "fromName": { + "type": "string", + "maxLength": 100 + }, + "replyTo": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + } + } } - }, - "required": [ - "country", - "state" - ] + } }, - "billing": { - "$ref": "#/components/schemas/Address" + "experimentalFlags": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } }, - "items": { + "friendlyId": { + "type": "object", + "properties": { + "characters": { + "type": "string", + "pattern": "^[^/?#&%<> ]+$", + "minLength": 2 + }, + "length": { + "type": "integer", + "minimum": 4, + "maximum": 32 + }, + "prefix": { + "type": "string", + "pattern": "^[^/?#&%<> ]+$", + "minLength": 1, + "maxLength": 8 + } + } + }, + "geoOverrides": { "type": "array", "items": { - "description": "A single line item in an order or estimate.", "type": "object", "properties": { - "name": { - "description": "Display name for this line item.", - "type": "string" - }, - "note": { - "description": "Optional customer note for this line item.", - "type": "string" - }, - "sku": { - "description": "SKU of the product.", - "type": "string" - }, - "path": { - "description": "Product page path.", - "type": "string" - }, - "imageUrl": { - "description": "Product image URL for order confirmation display.", - "type": "string" - }, - "productUrl": { - "description": "Canonical product URL.", - "type": "string" - }, - "quantity": { - "description": "Quantity ordered. Must be a whole number from 1 to 1000.", - "type": "integer", - "minimum": 1, - "maximum": 1000 + "country": { + "type": "string", + "pattern": "^[a-z]{2}$" }, - "price": { - "description": "Price information for a product or variant.", + "friendlyId": { "type": "object", "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" + "characters": { + "type": "string", + "pattern": "^[^/?#&%<> ]+$", + "minLength": 2 }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" + "length": { + "type": "integer", + "minimum": 4, + "maximum": 32 }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" + "prefix": { + "type": "string", + "pattern": "^[^/?#&%<> ]+$", + "minLength": 1, + "maxLength": 8 } } }, - "shippingDimensions": { - "description": "Physical dimensions used for shipping rate calculation.", + "emails": { "type": "object", "properties": { - "weight": { - "description": "Product weight for display and JSON-LD structured data.", + "branding": { "type": "object", "properties": { - "value": { - "description": "Numeric weight value.", - "type": "number" + "logoUrl": { + "type": "string", + "pattern": "^https:\\/\\/", + "maxLength": 1024 }, - "unit": { - "description": "Unit of weight measurement.", + "brandColor": { "type": "string", - "enum": [ - "kg", - "g", - "lb", - "oz" - ] + "pattern": "^#[0-9a-fA-F]{3,8}$|^[a-zA-Z]+$", + "maxLength": 20 + }, + "supportEmail": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "supportPhone": { + "type": "string", + "pattern": "^[^<>]*$", + "maxLength": 50 + }, + "footerAddress": { + "type": "string", + "pattern": "^[^<>]*$", + "maxLength": 500 } - }, - "required": [ - "value", - "unit" - ] - }, - "height": { - "description": "Height in the declared dimensionsUnit.", - "type": "number" - }, - "width": { - "description": "Width in the declared dimensionsUnit.", - "type": "number" - }, - "depth": { - "description": "Depth in the declared dimensionsUnit.", - "type": "number" + } }, - "dimensionsUnit": { - "description": "Unit of dimension measurement.", - "type": "string", - "enum": [ - "cm", - "mm", - "in" - ] + "transactional": { + "type": "object", + "properties": { + "sender": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "fromName": { + "type": "string", + "maxLength": 100 + }, + "replyTo": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + } + } } } }, - "selectedOptions": { - "description": "Option values selected by the customer.", + "experimentalFlags": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } + } + }, + "required": [ + "country" + ] + } + } + } + }, + "ProductBus": { + "description": "A Product Bus catalog entry representing a single product or configurable product.", + "type": "object", + "properties": { + "sku": { + "description": "Unique stock-keeping unit identifier.", + "type": "string" + }, + "path": { + "description": "URL path for this product (e.g. \"/products/my-product\").", + "type": "string", + "pattern": "^\\/([a-z0-9_]+([-_][a-z0-9_]+)*\\/)*[a-z0-9]+(-[a-z0-9]+)*$", + "maxLength": 900 + }, + "urlKey": { + "description": "URL key used to construct the canonical path.", + "type": "string" + }, + "description": { + "description": "Full product description.", + "type": "string" + }, + "name": { + "description": "Display name for the product.", + "type": "string" + }, + "metaTitle": { + "description": "HTML meta title override.", + "type": "string" + }, + "metaDescription": { + "description": "HTML meta description override.", + "type": "string" + }, + "gtin": { + "description": "Global Trade Item Number (barcode).", + "type": "string" + }, + "url": { + "description": "Canonical absolute URL for the product.", + "type": "string" + }, + "brand": { + "description": "Brand or manufacturer name.", + "type": "string" + }, + "type": { + "description": "Product type identifier (e.g. \"simple\", \"configurable\", \"bundle\").", + "type": "string" + }, + "availability": { + "description": "schema.org availability status for a product or offer.", + "type": "string", + "enum": [ + "BackOrder", + "Discontinued", + "InStock", + "InStoreOnly", + "LimitedAvailability", + "MadeToOrder", + "OnlineOnly", + "OutOfStock", + "PreOrder", + "PreSale", + "Reserved", + "SoldOut" + ] + }, + "availabilityDate": { + "description": "ISO 8601 date when the product becomes available.", + "type": "string" + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + }, + "itemCondition": { + "description": "schema.org item condition.", + "type": "string", + "enum": [ + "DamagedCondition", + "NewCondition", + "RefurbishedCondition", + "UsedCondition" + ] + }, + "metadata": { + "description": "Arbitrary key/value metadata attached to the product.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "options": { + "description": "Configurable options available for this product (e.g. Color, Size).", + "type": "array", + "items": { + "description": "A configurable product option with its available values (e.g. Color, Size).", + "type": "object", + "properties": { + "id": { + "description": "Option identifier, typically matching the attribute code.", + "type": "string" + }, + "label": { + "description": "Display label for the option group (e.g. \"Color\").", + "type": "string" + }, + "position": { + "description": "Sort order for display.", + "type": "number" + }, + "values": { + "description": "Available values for this option.", "type": "array", "items": { - "description": "A customer-selected option value for a line item (e.g. color=Red).", + "description": "A single selectable value for a product option.", "type": "object", "properties": { "id": { - "description": "Option identifier.", + "description": "Unique identifier for this option value.", "type": "string" }, "value": { - "description": "Selected value.", + "description": "Display label for this option value (e.g. \"Red\", \"Large\").", "type": "string" - } - }, + }, + "uid": { + "description": "Internal UID used by some backends.", + "type": "string" + } + }, "required": [ - "id", "value" ] } + } + }, + "required": [ + "label", + "values" + ] + } + }, + "aggregateRating": { + "description": "Aggregate customer rating for schema.org structured data.", + "type": "object", + "properties": { + "ratingValue": { + "description": "Average rating value. Numeric string; converted to a number in JSON-LD.", + "type": "string" + }, + "reviewCount": { + "description": "Total number of ratings. Numeric string; converted to an integer in JSON-LD.", + "type": "string" + }, + "bestRating": { + "description": "Best possible rating. Numeric string.", + "type": "string" + }, + "worstRating": { + "description": "Worst possible rating. Numeric string.", + "type": "string" + } + } + }, + "images": { + "description": "Product images.", + "type": "array", + "items": { + "description": "Product media asset. An image, or a video when the video field is set.", + "type": "object", + "properties": { + "url": { + "description": "Absolute URL of the image.", + "type": "string" }, - "bundleItems": { - "description": "Resolved bundle component line items nested on a bundle parent. Not counted toward the order subtotal -- the parent price is the chargeable value.", + "label": { + "description": "Accessible alt text for the image.", + "type": "string" + }, + "filename": { + "description": "Original filename of the image.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+$" + }, + "roles": { + "description": "Semantic roles assigned to this image, e.g. \"thumbnail\".", "type": "array", "items": { - "description": "A resolved bundle component line item nested on a bundle parent order item.", + "type": "string" + } + }, + "video": { + "description": "Absolute URL of an associated video asset, when this media entry represents a video.", + "type": "string" + } + }, + "required": [ + "url" + ] + } + }, + "variants": { + "description": "Available variants for a configurable product.", + "type": "array", + "items": { + "description": "A purchasable variant of a configurable product.", + "type": "object", + "properties": { + "sku": { + "description": "Unique stock-keeping unit identifier.", + "type": "string" + }, + "name": { + "description": "Display name for this variant.", + "type": "string" + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + }, + "url": { + "description": "Canonical URL for this variant.", + "type": "string" + }, + "images": { + "description": "Images for this variant.", + "type": "array", + "items": { + "description": "Product media asset. An image, or a video when the video field is set.", "type": "object", "properties": { - "name": { - "description": "Display name of the component.", + "url": { + "description": "Absolute URL of the image.", "type": "string" }, - "sku": { - "description": "SKU of the component.", + "label": { + "description": "Accessible alt text for the image.", "type": "string" }, - "path": { - "description": "Product page path of the component.", + "filename": { + "description": "Original filename of the image.", + "type": "string", + "pattern": "^[A-Za-z0-9_-]+$" + }, + "roles": { + "description": "Semantic roles assigned to this image, e.g. \"thumbnail\".", + "type": "array", + "items": { + "type": "string" + } + }, + "video": { + "description": "Absolute URL of an associated video asset, when this media entry represents a video.", + "type": "string" + } + }, + "required": [ + "url" + ] + } + }, + "gtin": { + "description": "Global Trade Item Number (barcode).", + "type": "string" + }, + "description": { + "description": "Variant-specific description.", + "type": "string" + }, + "availability": { + "description": "schema.org availability status for a product or offer.", + "type": "string", + "enum": [ + "BackOrder", + "Discontinued", + "InStock", + "InStoreOnly", + "LimitedAvailability", + "MadeToOrder", + "OnlineOnly", + "OutOfStock", + "PreOrder", + "PreSale", + "Reserved", + "SoldOut" + ] + }, + "options": { + "description": "Option values that identify this variant (e.g. color=Red, size=Large).", + "type": "array", + "items": { + "description": "A single selectable value for a product option.", + "type": "object", + "properties": { + "id": { + "description": "Unique identifier for this option value.", "type": "string" }, - "quantity": { - "description": "Quantity ordered. Must be a whole number from 1 to 1000.", - "type": "integer", - "minimum": 1, - "maximum": 1000 + "value": { + "description": "Display label for this option value (e.g. \"Red\", \"Large\").", + "type": "string" }, - "price": { - "description": "Price information for a product or variant.", - "type": "object", - "properties": { - "final": { - "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", - "type": "string" - }, - "currency": { - "description": "ISO 4217 currency code, e.g. \"USD\".", - "type": "string" - }, - "regular": { - "description": "Original price before any discount, as a decimal string.", - "type": "string" - } - } + "uid": { + "description": "Internal UID used by some backends.", + "type": "string" } }, "required": [ - "path", - "quantity", - "price" + "value" ] } }, + "itemCondition": { + "description": "schema.org item condition.", + "type": "string", + "enum": [ + "DamagedCondition", + "NewCondition", + "RefurbishedCondition", + "UsedCondition" + ] + }, "custom": { - "description": "Arbitrary custom data for this line item.", "type": "object", "additionalProperties": true - } - }, - "required": [ - "sku", - "path", - "quantity", - "price" - ] - } + }, + "jsonldExtensions": { + "description": "Additional schema.org properties shallow-merged into this variant's Offer in the auto-generated JSON-LD. Max 16,000 characters when serialized.", + "type": "object", + "additionalProperties": true + }, + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "shippingDimensions": { + "description": "Physical dimensions used for shipping rate calculation.", + "type": "object", + "properties": { + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "height": { + "description": "Height in the declared dimensionsUnit.", + "type": "number" + }, + "width": { + "description": "Width in the declared dimensionsUnit.", + "type": "number" + }, + "depth": { + "description": "Depth in the declared dimensionsUnit.", + "type": "number" + }, + "dimensionsUnit": { + "description": "Unit of dimension measurement.", + "type": "string", + "enum": [ + "cm", + "mm", + "in" + ] + } + } + } + }, + "required": [ + "sku", + "name", + "url", + "images" + ] + } + }, + "jsonld": { + "description": "Full JSON-LD override. When present, replaces the auto-generated structured data.", + "type": "string", + "maxLength": 128000 + }, + "custom": { + "type": "object", + "additionalProperties": true + }, + "jsonldExtensions": { + "description": "Additional schema.org properties shallow-merged into the auto-generated Product JSON-LD object. Ignored when jsonld override is used. Max 32,000 characters when serialized.", + "type": "object", + "additionalProperties": true + }, + "shipping": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "A single shipping option in Google Merchant Center format.", + "type": "object", + "properties": { + "country": { + "description": "Two-letter country code (ISO 3166-1 alpha-2).", + "type": "string" + }, + "region": { + "description": "State or region code.", + "type": "string" + }, + "service": { + "description": "Shipping service label (e.g. \"Standard\", \"Overnight\").", + "type": "string" + }, + "price": { + "description": "Shipping cost with currency code (e.g. \"16.00 USD\").", + "type": "string" + }, + "min_handling_time": { + "description": "Minimum order handling time in business days.", + "type": "string" + }, + "max_handling_time": { + "description": "Maximum order handling time in business days.", + "type": "string" + }, + "min_transit_time": { + "description": "Minimum shipping transit time in business days.", + "type": "string" + }, + "max_transit_time": { + "description": "Maximum shipping transit time in business days.", + "type": "string" + } + } + }, + { + "type": "array", + "items": { + "description": "A single shipping option in Google Merchant Center format.", + "type": "object", + "properties": { + "country": { + "description": "Two-letter country code (ISO 3166-1 alpha-2).", + "type": "string" + }, + "region": { + "description": "State or region code.", + "type": "string" + }, + "service": { + "description": "Shipping service label (e.g. \"Standard\", \"Overnight\").", + "type": "string" + }, + "price": { + "description": "Shipping cost with currency code (e.g. \"16.00 USD\").", + "type": "string" + }, + "min_handling_time": { + "description": "Minimum order handling time in business days.", + "type": "string" + }, + "max_handling_time": { + "description": "Maximum order handling time in business days.", + "type": "string" + }, + "min_transit_time": { + "description": "Minimum shipping transit time in business days.", + "type": "string" + }, + "max_transit_time": { + "description": "Maximum shipping transit time in business days.", + "type": "string" + } + } + } + } + ] + }, + "bundleItems": { + "description": "Bundle composition. Presence of this array (regardless of contents) marks this product as a bundle.", + "type": "array", + "items": { + "description": "One entry in a bundle product's composition. May be a simple item (sku + price) or a configurable item (variants array). Presence of the parent product's bundleItems array marks it as a bundle.", + "type": "object", + "properties": { + "sku": { + "description": "SKU for a simple bundle item.", + "type": "string" + }, + "name": { + "description": "Display name for a simple bundle item.", + "type": "string" + }, + "price": { + "description": "Price for a bundle component. Narrower than ProductBusPrice -- no currency field (currency comes from the parent line item).", + "type": "object", + "properties": { + "final": { + "description": "Component price as a decimal string.", + "type": "string" + }, + "regular": { + "description": "Pre-discount price for display purposes.", + "type": "string" + } + }, + "required": [ + "final" + ] + }, + "variants": { + "description": "Variants for a configurable bundle item. When present, the server selects one variant at preview time.", + "type": "array", + "items": { + "description": "One variant of a configurable bundle item. The server selects the variant whose options are all satisfied by the parent line item's selectedOptions.", + "type": "object", + "properties": { + "sku": { + "description": "SKU for this variant.", + "type": "string" + }, + "name": { + "description": "Display name for this variant.", + "type": "string" + }, + "price": { + "description": "Price for a bundle component. Narrower than ProductBusPrice -- no currency field (currency comes from the parent line item).", + "type": "object", + "properties": { + "final": { + "description": "Component price as a decimal string.", + "type": "string" + }, + "regular": { + "description": "Pre-discount price for display purposes.", + "type": "string" + } + }, + "required": [ + "final" + ] + }, + "options": { + "description": "Option pairs that identify this variant.", + "type": "array", + "items": { + "description": "Option pair on a configurable bundle item variant. The server resolves which variant to ship by matching every entry here against the parent line item's selectedOptions.", + "type": "object", + "properties": { + "id": { + "description": "Option identifier, matched against selectedOptions[].id.", + "type": "string" + }, + "name": { + "description": "Option value label, matched against selectedOptions[].value.", + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + } + }, + "taxCode": { + "description": "Per-variant tax classification code. Falls back to the bundle parent's taxCode when absent.", + "type": "string", + "maxLength": 255 + }, + "taxData": { + "description": "Supplementary tax data. Falls back to the bundle parent's taxData when absent.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "sku", + "price", + "options" + ] + } + }, + "taxCode": { + "description": "Per-component tax classification code. Falls back to the bundle parent's taxCode when absent.", + "type": "string", + "maxLength": 255 + }, + "taxData": { + "description": "Supplementary tax data. Falls back to the bundle parent's taxData when absent.", + "type": "object", + "additionalProperties": true + } + } + } + }, + "feeds": { + "description": "Feed configuration for product distribution.", + "type": "object", + "properties": { + "common": { + "description": "Common feed settings shared across product distribution channels.", + "type": "object", + "properties": { + "geoTargetCountries": { + "description": "Target countries for product feeds.", + "type": "array", + "items": { + "type": "string" + } + }, + "geoStoreCountry": { + "description": "Store country for feed generation.", + "type": "string" + } + } + }, + "oai": { + "description": "Product feed eligibility for the OpenAI / agentic commerce feed.", + "type": "object", + "properties": { + "isEligibleForSearch": { + "description": "Whether the product is eligible for search feeds.", + "type": "boolean" + }, + "isEligibleForCheckout": { + "description": "Whether the product supports checkout via feeds.", + "type": "boolean" + } + }, + "required": [ + "isEligibleForSearch", + "isEligibleForCheckout" + ] + } + } + }, + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "shippingDimensions": { + "description": "Physical dimensions used for shipping rate calculation.", + "type": "object", + "properties": { + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "height": { + "description": "Height in the declared dimensionsUnit.", + "type": "number" + }, + "width": { + "description": "Width in the declared dimensionsUnit.", + "type": "number" + }, + "depth": { + "description": "Depth in the declared dimensionsUnit.", + "type": "number" + }, + "dimensionsUnit": { + "description": "Unit of dimension measurement.", + "type": "string", + "enum": [ + "cm", + "mm", + "in" + ] + } + } + }, + "taxCode": { + "description": "Tax classification code for this product.", + "type": "string", + "maxLength": 255 + }, + "taxData": { + "description": "Supplementary tax data passed to the tax provider.", + "type": "object", + "additionalProperties": true + }, + "country": { + "description": "ISO 3166-1 alpha-2 store country code.", + "type": "string", + "pattern": "^[a-z]{2}$" + }, + "locale": { + "description": "BCP-47 locale tag for this product entry.", + "type": "string", + "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" + } + }, + "required": [ + "sku", + "name", + "path" + ] + }, + "Order": { + "type": "object", + "properties": { + "customer": { + "$ref": "#/components/schemas/Customer" + }, + "shipping": { + "$ref": "#/components/schemas/Address" + }, + "billing": { + "$ref": "#/components/schemas/Address" + }, + "items": { + "type": "array", + "items": { + "description": "A single line item in an order or estimate.", + "type": "object", + "properties": { + "name": { + "description": "Display name for this line item.", + "type": "string" + }, + "note": { + "description": "Optional customer note for this line item.", + "type": "string" + }, + "sku": { + "description": "SKU of the product.", + "type": "string" + }, + "path": { + "description": "Product page path.", + "type": "string" + }, + "imageUrl": { + "description": "Product image URL for order confirmation display.", + "type": "string" + }, + "productUrl": { + "description": "Canonical product URL.", + "type": "string" + }, + "quantity": { + "description": "Quantity ordered. Must be a whole number from 1 to 1000.", + "type": "integer", + "minimum": 1, + "maximum": 1000 + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + }, + "shippingDimensions": { + "description": "Physical dimensions used for shipping rate calculation.", + "type": "object", + "properties": { + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "height": { + "description": "Height in the declared dimensionsUnit.", + "type": "number" + }, + "width": { + "description": "Width in the declared dimensionsUnit.", + "type": "number" + }, + "depth": { + "description": "Depth in the declared dimensionsUnit.", + "type": "number" + }, + "dimensionsUnit": { + "description": "Unit of dimension measurement.", + "type": "string", + "enum": [ + "cm", + "mm", + "in" + ] + } + } + }, + "selectedOptions": { + "description": "Option values selected by the customer.", + "type": "array", + "items": { + "description": "A customer-selected option value for a line item (e.g. color=Red).", + "type": "object", + "properties": { + "id": { + "description": "Option identifier.", + "type": "string" + }, + "value": { + "description": "Selected value.", + "type": "string" + } + }, + "required": [ + "id", + "value" + ] + } + }, + "bundleItems": { + "description": "Resolved bundle component line items nested on a bundle parent. Not counted toward the order subtotal -- the parent price is the chargeable value.", + "type": "array", + "items": { + "description": "A resolved bundle component line item nested on a bundle parent order item.", + "type": "object", + "properties": { + "name": { + "description": "Display name of the component.", + "type": "string" + }, + "sku": { + "description": "SKU of the component.", + "type": "string" + }, + "path": { + "description": "Product page path of the component.", + "type": "string" + }, + "quantity": { + "description": "Quantity ordered. Must be a whole number from 1 to 1000.", + "type": "integer", + "minimum": 1, + "maximum": 1000 + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + } + }, + "required": [ + "path", + "quantity", + "price" + ] + } + }, + "custom": { + "description": "Arbitrary custom data for this line item.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "sku", + "path", + "quantity", + "price" + ] + } + }, + "country": { + "type": "string", + "pattern": "^[a-z]{2}$" + }, + "locale": { + "type": "string", + "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" + }, + "shippingMethod": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "estimateToken": { + "type": "string" + }, + "paymentMethod": { + "type": "string" + }, + "checkoutFlow": { + "description": "Checkout flow type. `express` identifies wallet or shortcut checkout flows.", + "type": "string", + "enum": [ + "standard", + "express" + ] + }, + "entryPoint": { + "description": "Page or experience where checkout started.", + "type": "string", + "enum": [ + "cart", + "checkout", + "pdp" + ] + }, + "couponCode": { + "type": "string" + }, + "giftMessage": { + "type": "string", + "maxLength": 250 + }, + "customerTimezone": { + "type": "string", + "pattern": "^[A-Za-z0-9_+\\-/]+$", + "maxLength": 100 + }, + "custom": { + "type": "object", + "additionalProperties": { + "type": "string", + "maxLength": 2048 + } + } + }, + "required": [ + "items", + "customer", + "shipping", + "country", + "locale" + ] + }, + "PreviewOrder": { + "type": "object", + "properties": { + "customer": { + "$ref": "#/components/schemas/Customer" + }, + "shipping": { + "description": "A shipping or billing address.", + "type": "object", + "properties": { + "name": { + "description": "Full name of the recipient.", + "type": "string", + "maxLength": 255 + }, + "company": { + "description": "Company name.", + "type": "string", + "maxLength": 255 + }, + "address1": { + "description": "Primary street address line.", + "type": "string", + "maxLength": 255 + }, + "address2": { + "description": "Secondary address line (apartment, suite, etc.).", + "type": "string", + "maxLength": 255 + }, + "city": { + "description": "City name.", + "type": "string", + "maxLength": 255 + }, + "state": { + "description": "State or province code.", + "type": "string", + "maxLength": 255 + }, + "zip": { + "description": "Postal or ZIP code.", + "type": "string", + "maxLength": 255 + }, + "country": { + "description": "ISO 3166-1 alpha-2 country code.", + "type": "string", + "maxLength": 255 + }, + "phone": { + "description": "Phone number.", + "type": "string", + "maxLength": 255 + }, + "email": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "isDefault": { + "description": "Whether this is the default address for the customer.", + "type": "boolean" + }, + "isValidated": { + "description": "Whether this address has been validated by an address verification service.", + "type": "boolean" + } + }, + "required": [ + "country", + "state" + ] + }, + "billing": { + "$ref": "#/components/schemas/Address" + }, + "items": { + "type": "array", + "items": { + "description": "A single line item in an order or estimate.", + "type": "object", + "properties": { + "name": { + "description": "Display name for this line item.", + "type": "string" + }, + "note": { + "description": "Optional customer note for this line item.", + "type": "string" + }, + "sku": { + "description": "SKU of the product.", + "type": "string" + }, + "path": { + "description": "Product page path.", + "type": "string" + }, + "imageUrl": { + "description": "Product image URL for order confirmation display.", + "type": "string" + }, + "productUrl": { + "description": "Canonical product URL.", + "type": "string" + }, + "quantity": { + "description": "Quantity ordered. Must be a whole number from 1 to 1000.", + "type": "integer", + "minimum": 1, + "maximum": 1000 + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + }, + "shippingDimensions": { + "description": "Physical dimensions used for shipping rate calculation.", + "type": "object", + "properties": { + "weight": { + "description": "Product weight for display and JSON-LD structured data.", + "type": "object", + "properties": { + "value": { + "description": "Numeric weight value.", + "type": "number" + }, + "unit": { + "description": "Unit of weight measurement.", + "type": "string", + "enum": [ + "kg", + "g", + "lb", + "oz" + ] + } + }, + "required": [ + "value", + "unit" + ] + }, + "height": { + "description": "Height in the declared dimensionsUnit.", + "type": "number" + }, + "width": { + "description": "Width in the declared dimensionsUnit.", + "type": "number" + }, + "depth": { + "description": "Depth in the declared dimensionsUnit.", + "type": "number" + }, + "dimensionsUnit": { + "description": "Unit of dimension measurement.", + "type": "string", + "enum": [ + "cm", + "mm", + "in" + ] + } + } + }, + "selectedOptions": { + "description": "Option values selected by the customer.", + "type": "array", + "items": { + "description": "A customer-selected option value for a line item (e.g. color=Red).", + "type": "object", + "properties": { + "id": { + "description": "Option identifier.", + "type": "string" + }, + "value": { + "description": "Selected value.", + "type": "string" + } + }, + "required": [ + "id", + "value" + ] + } + }, + "bundleItems": { + "description": "Resolved bundle component line items nested on a bundle parent. Not counted toward the order subtotal -- the parent price is the chargeable value.", + "type": "array", + "items": { + "description": "A resolved bundle component line item nested on a bundle parent order item.", + "type": "object", + "properties": { + "name": { + "description": "Display name of the component.", + "type": "string" + }, + "sku": { + "description": "SKU of the component.", + "type": "string" + }, + "path": { + "description": "Product page path of the component.", + "type": "string" + }, + "quantity": { + "description": "Quantity ordered. Must be a whole number from 1 to 1000.", + "type": "integer", + "minimum": 1, + "maximum": 1000 + }, + "price": { + "description": "Price information for a product or variant.", + "type": "object", + "properties": { + "final": { + "description": "Final price the customer pays, as a decimal string (e.g. \"19.99\").", + "type": "string" + }, + "currency": { + "description": "ISO 4217 currency code, e.g. \"USD\".", + "type": "string" + }, + "regular": { + "description": "Original price before any discount, as a decimal string.", + "type": "string" + } + } + } + }, + "required": [ + "path", + "quantity", + "price" + ] + } + }, + "custom": { + "description": "Arbitrary custom data for this line item.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "sku", + "path", + "quantity", + "price" + ] + } + }, + "country": { + "type": "string", + "pattern": "^[a-z]{2}$" + }, + "locale": { + "type": "string", + "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" + }, + "shippingMethod": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "estimateToken": { + "type": "string" + }, + "paymentMethod": { + "type": "string" + }, + "checkoutFlow": { + "description": "Checkout flow type. `express` identifies wallet or shortcut checkout flows.", + "type": "string", + "enum": [ + "standard", + "express" + ] + }, + "entryPoint": { + "description": "Page or experience where checkout started.", + "type": "string", + "enum": [ + "cart", + "checkout", + "pdp" + ] + }, + "couponCode": { + "type": "string" + }, + "giftMessage": { + "type": "string", + "maxLength": 250 + }, + "customerTimezone": { + "type": "string", + "pattern": "^[A-Za-z0-9_+\\-/]+$", + "maxLength": 100 + }, + "custom": { + "type": "object", + "additionalProperties": { + "type": "string", + "maxLength": 2048 + } + }, + "couponSource": { + "type": "string" + } + }, + "required": [ + "items", + "shipping" + ] + }, + "Customer": { + "description": "Customer contact information provided at checkout.", + "type": "object", + "properties": { + "firstName": { + "description": "Customer first name.", + "type": "string", + "maxLength": 255 + }, + "lastName": { + "description": "Customer last name.", + "type": "string", + "maxLength": 255 + }, + "email": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "phone": { + "description": "Customer phone number.", + "type": "string" + } + }, + "required": [ + "firstName", + "lastName", + "email" + ] + }, + "Address": { + "description": "A shipping or billing address.", + "type": "object", + "properties": { + "name": { + "description": "Full name of the recipient.", + "type": "string", + "maxLength": 255 + }, + "company": { + "description": "Company name.", + "type": "string", + "maxLength": 255 + }, + "address1": { + "description": "Primary street address line.", + "type": "string", + "maxLength": 255 + }, + "address2": { + "description": "Secondary address line (apartment, suite, etc.).", + "type": "string", + "maxLength": 255 + }, + "city": { + "description": "City name.", + "type": "string", + "maxLength": 255 + }, + "state": { + "description": "State or province code.", + "type": "string", + "maxLength": 255 + }, + "zip": { + "description": "Postal or ZIP code.", + "type": "string", + "maxLength": 255 + }, + "country": { + "description": "ISO 3166-1 alpha-2 country code.", + "type": "string", + "maxLength": 255 + }, + "phone": { + "description": "Phone number.", + "type": "string", + "maxLength": 255 + }, + "email": { + "type": "string", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "maxLength": 255 + }, + "isDefault": { + "description": "Whether this is the default address for the customer.", + "type": "boolean" + }, + "isValidated": { + "description": "Whether this address has been validated by an address verification service.", + "type": "boolean" + } + }, + "required": [ + "name", + "email", + "address1", + "city", + "state", + "zip", + "country" + ] + }, + "FlatCouponType": { + "description": "A coupon type applying a flat percentage or fixed discount. Mutually exclusive with the product-list shape (`discountedProducts`).", + "type": "object", + "properties": { + "id": { + "description": "Unique coupon type identifier.", + "type": "string", + "minLength": 1 + }, + "name": { + "description": "Human-readable name.", + "type": "string", + "minLength": 1 + }, + "minimumOrderAmount": { + "description": "Minimum pre-discount subtotal required to apply. Defaults to 0.", + "type": "number", + "minimum": 0 + }, + "maximumDiscountAmount": { + "description": "Cap on the discount amount (percentage coupons); null for no cap.", + "type": [ + "number", + "null" + ] + }, + "freeShipping": { + "description": "Grants free shipping when applied.", + "type": "boolean" + }, + "includedShippingTypes": { + "description": "When set, free shipping applies only to these shipping method types.", + "type": "array", + "items": { + "type": "string" + } + }, + "includedCategories": { + "description": "Categories the coupon applies to.", + "type": "array", + "items": { + "type": "string" + } + }, + "excludedCategories": { + "description": "Categories excluded from the coupon.", + "type": "array", + "items": { + "type": "string" + } + }, + "stackable": { + "description": "Whether the coupon stacks with cart-level auto pricing rules. Defaults to true.", + "type": "boolean" + }, + "autoApply": { + "description": "Apply automatically without manual code entry. Defaults to false.", + "type": "boolean" + }, + "allowManualEntry": { + "description": "Allow the code to be entered manually at checkout. Defaults to true.", + "type": "boolean" + }, + "defaultUsageLimit": { + "description": "Default total usage limit for codes of this type; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "defaultUsesPerCode": { + "description": "Default per-code usage limit; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "notes": { + "description": "Free-form operator notes.", + "type": "string" + }, + "country": { + "description": "Single ISO 3166-1 alpha-2 country the coupon is valid in. Mutually exclusive with `countries`.", + "type": "string", + "pattern": "^[a-z]{2}$" + }, + "countries": { + "description": "ISO 3166-1 alpha-2 countries the coupon is valid in. Mutually exclusive with `country`.", + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-z]{2}$" + } + }, + "locale": { + "description": "BCP-47 locale the coupon is scoped to.", + "type": "string", + "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" + }, + "createdAt": { + "description": "Creation timestamp (ISO 8601). Managed by the service; ignored on write.", + "type": "string" + }, + "updatedAt": { + "description": "Last-update timestamp (ISO 8601). Managed by the service; ignored on write.", + "type": "string" + }, + "discountType": { + "description": "Whether `discountValue` is a percentage or a fixed cash amount.", + "type": "string", + "enum": [ + "percentage", + "fixed" + ] + }, + "discountValue": { + "description": "Discount magnitude — a percentage (0–100) when `discountType` is \"percentage\", otherwise a cash amount. Defaults to 0.", + "type": "number", + "minimum": 0 + }, + "includedProducts": { + "description": "When non-empty, only these products count toward the coupon. Each entry is a path string or a `{ path, sku? }` object.", + "type": "array", + "items": { + "anyOf": [] + } + }, + "excludedProducts": { + "description": "Products excluded from the coupon. Each entry is a path string or a `{ path, sku? }` object.", + "type": "array", + "items": { + "anyOf": [] + } + }, + "excludeDiscountedProducts": { + "description": "When true, apply only to full-price lines (regular price equals sale price).", + "type": "boolean" + }, + "applyToSalePrice": { + "description": "When false (default) the discount is computed against the regular price with cheaper-wins; when true it stacks on the current sale price.", + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "discountType" + ] + }, + "ProductListCouponType": { + "description": "A coupon type that sets absolute per-product prices via `discountedProducts`. The entries define their own scope; mutually exclusive with the flat discount and scoping/pricing fields (`discountType`, `discountValue`, `includedProducts`, `excludedProducts`, `includedCategories`, `excludedCategories`, `excludeDiscountedProducts`, `applyToSalePrice`).", + "type": "object", + "properties": { + "id": { + "description": "Unique coupon type identifier.", + "type": "string", + "minLength": 1 + }, + "name": { + "description": "Human-readable name.", + "type": "string", + "minLength": 1 + }, + "minimumOrderAmount": { + "description": "Minimum pre-discount subtotal required to apply. Defaults to 0.", + "type": "number", + "minimum": 0 + }, + "maximumDiscountAmount": { + "description": "Cap on the discount amount (percentage coupons); null for no cap.", + "type": [ + "number", + "null" + ] + }, + "freeShipping": { + "description": "Grants free shipping when applied.", + "type": "boolean" + }, + "includedShippingTypes": { + "description": "When set, free shipping applies only to these shipping method types.", + "type": "array", + "items": { + "type": "string" + } + }, + "includedCategories": { + "description": "Categories the coupon applies to.", + "type": "array", + "items": { + "type": "string" + } + }, + "excludedCategories": { + "description": "Categories excluded from the coupon.", + "type": "array", + "items": { + "type": "string" + } + }, + "stackable": { + "description": "Whether the coupon stacks with cart-level auto pricing rules. Defaults to true.", + "type": "boolean" + }, + "autoApply": { + "description": "Apply automatically without manual code entry. Defaults to false.", + "type": "boolean" + }, + "allowManualEntry": { + "description": "Allow the code to be entered manually at checkout. Defaults to true.", + "type": "boolean" + }, + "defaultUsageLimit": { + "description": "Default total usage limit for codes of this type; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "defaultUsesPerCode": { + "description": "Default per-code usage limit; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "notes": { + "description": "Free-form operator notes.", + "type": "string" }, "country": { + "description": "Single ISO 3166-1 alpha-2 country the coupon is valid in. Mutually exclusive with `countries`.", "type": "string", "pattern": "^[a-z]{2}$" }, + "countries": { + "description": "ISO 3166-1 alpha-2 countries the coupon is valid in. Mutually exclusive with `country`.", + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-z]{2}$" + } + }, "locale": { + "description": "BCP-47 locale the coupon is scoped to.", "type": "string", "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" }, - "shippingMethod": { - "type": "object", - "properties": { - "id": { - "type": "string" - } + "createdAt": { + "description": "Creation timestamp (ISO 8601). Managed by the service; ignored on write.", + "type": "string" + }, + "updatedAt": { + "description": "Last-update timestamp (ISO 8601). Managed by the service; ignored on write.", + "type": "string" + }, + "discountedProducts": { + "description": "Per-product absolute price overrides. Exact duplicates (same path, or same path + sku) are rejected.", + "type": "array", + "items": { + "$ref": "#/components/schemas/DiscountedProduct" }, - "required": [ - "id" + "minItems": 1 + } + }, + "required": [ + "id", + "name", + "discountedProducts" + ] + }, + "CouponTypeUpdate": { + "description": "Partial coupon type fields to merge into the existing type. `id` and timestamps are immutable.", + "type": "object", + "properties": { + "name": { + "description": "Human-readable name.", + "type": "string", + "minLength": 1 + }, + "minimumOrderAmount": { + "description": "Minimum pre-discount subtotal required to apply. Defaults to 0.", + "type": "number", + "minimum": 0 + }, + "maximumDiscountAmount": { + "description": "Cap on the discount amount (percentage coupons); null for no cap.", + "type": [ + "number", + "null" ] }, - "estimateToken": { - "type": "string" + "freeShipping": { + "description": "Grants free shipping when applied.", + "type": "boolean" }, - "paymentMethod": { - "type": "string" + "includedShippingTypes": { + "description": "When set, free shipping applies only to these shipping method types.", + "type": "array", + "items": { + "type": "string" + } }, - "couponCode": { + "includedCategories": { + "description": "Categories the coupon applies to.", + "type": "array", + "items": { + "type": "string" + } + }, + "excludedCategories": { + "description": "Categories excluded from the coupon.", + "type": "array", + "items": { + "type": "string" + } + }, + "stackable": { + "description": "Whether the coupon stacks with cart-level auto pricing rules. Defaults to true.", + "type": "boolean" + }, + "autoApply": { + "description": "Apply automatically without manual code entry. Defaults to false.", + "type": "boolean" + }, + "allowManualEntry": { + "description": "Allow the code to be entered manually at checkout. Defaults to true.", + "type": "boolean" + }, + "defaultUsageLimit": { + "description": "Default total usage limit for codes of this type; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "defaultUsesPerCode": { + "description": "Default per-code usage limit; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "notes": { + "description": "Free-form operator notes.", "type": "string" }, - "giftMessage": { + "country": { + "description": "Single ISO 3166-1 alpha-2 country the coupon is valid in. Mutually exclusive with `countries`.", "type": "string", - "maxLength": 250 + "pattern": "^[a-z]{2}$" }, - "customerTimezone": { + "countries": { + "description": "ISO 3166-1 alpha-2 countries the coupon is valid in. Mutually exclusive with `country`.", + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-z]{2}$" + } + }, + "locale": { + "description": "BCP-47 locale the coupon is scoped to.", "type": "string", - "pattern": "^[A-Za-z0-9_+\\-/]+$", - "maxLength": 100 + "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2}|-[0-9]{3})?$" }, - "custom": { - "type": "object", - "additionalProperties": { - "type": "string", - "maxLength": 2048 + "discountType": { + "description": "Whether `discountValue` is a percentage or a fixed cash amount.", + "type": "string", + "enum": [ + "percentage", + "fixed" + ] + }, + "discountValue": { + "description": "Discount magnitude — a percentage (0–100) when `discountType` is \"percentage\", otherwise a cash amount. Defaults to 0.", + "type": "number", + "minimum": 0 + }, + "includedProducts": { + "description": "When non-empty, only these products count toward the coupon. Each entry is a path string or a `{ path, sku? }` object.", + "type": "array", + "items": { + "anyOf": [] } }, - "couponSource": { + "excludedProducts": { + "description": "Products excluded from the coupon. Each entry is a path string or a `{ path, sku? }` object.", + "type": "array", + "items": { + "anyOf": [] + } + }, + "excludeDiscountedProducts": { + "description": "When true, apply only to full-price lines (regular price equals sale price).", + "type": "boolean" + }, + "applyToSalePrice": { + "description": "When false (default) the discount is computed against the regular price with cheaper-wins; when true it stacks on the current sale price.", + "type": "boolean" + }, + "discountedProducts": { + "description": "Per-product absolute price overrides. Exact duplicates (same path, or same path + sku) are rejected.", + "type": "array", + "items": { + "$ref": "#/components/schemas/DiscountedProduct" + }, + "minItems": 1 + } + } + }, + "DiscountedProduct": { + "description": "Maps a product path (optionally a variant via `sku`) to an absolute final per-unit price.", + "type": "object", + "properties": { + "path": { + "description": "Product path the price applies to.", + "type": "string", + "minLength": 1 + }, + "sku": { + "description": "Optional variant SKU. Omit to match any variant at the path. A path + sku entry takes precedence over a path-only entry for the same line.", "type": "string" + }, + "price": { + "anyOf": [ + { + "description": "Price as a decimal string, e.g. \"19.99\".", + "type": "string", + "pattern": "^\\d+(\\.\\d+)?$" + }, + { + "description": "Price as a non-negative number.", + "type": "number", + "minimum": 0 + } + ] } }, "required": [ - "items", - "shipping" + "path", + "price" ] }, - "Customer": { - "description": "Customer contact information provided at checkout.", + "CouponCode": { + "description": "A single coupon code referencing a coupon type.", "type": "object", "properties": { - "firstName": { - "description": "Customer first name.", + "code": { + "description": "The coupon code (case-insensitive; normalized to uppercase). Letters, digits, hyphens, underscores; max 64 chars.", "type": "string", - "maxLength": 255 + "maxLength": 64 }, - "lastName": { - "description": "Customer last name.", - "type": "string", - "maxLength": 255 + "typeId": { + "description": "Identifier of the coupon type this code draws its discount from.", + "type": "string" }, - "email": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + "discountOverride": { + "description": "Overrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.", + "type": [ + "object", + "null" + ], + "properties": { + "discountType": { + "type": "string", + "enum": [ + "percentage", + "fixed" + ] + }, + "discountValue": { + "type": "number", + "minimum": 0 + } + }, + "required": [ + "discountType", + "discountValue" + ] }, - "phone": { - "description": "Customer phone number.", + "usageLimit": { + "description": "Total redemption limit; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "usageCount": { + "description": "Times redeemed. Managed by the service; ignored on write.", + "type": "integer", + "minimum": 0 + }, + "usesPerCustomer": { + "description": "Per-customer redemption limit; null for unlimited.", + "type": [ + "number", + "null" + ] + }, + "expiresAt": { + "description": "Expiry timestamp (ISO 8601). Omit for a code that never expires.", + "type": "string" + }, + "active": { + "description": "Whether the code can be redeemed. Defaults to true.", + "type": "boolean" + }, + "createdAt": { + "description": "Creation timestamp (ISO 8601). Managed by the service.", + "type": "string" + }, + "updatedAt": { + "description": "Last-update timestamp (ISO 8601). Managed by the service.", "type": "string" } }, "required": [ - "firstName", - "lastName", - "email" + "code", + "typeId" ] }, - "Address": { - "description": "A shipping or billing address.", + "CouponCodeUpdate": { + "description": "Partial coupon code fields to merge into the existing code. `code`, `typeId`, `usageCount`, and timestamps are immutable.", "type": "object", "properties": { - "name": { - "description": "Full name of the recipient.", - "type": "string", - "maxLength": 255 - }, - "company": { - "description": "Company name.", - "type": "string", - "maxLength": 255 + "discountOverride": { + "description": "Overrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.", + "type": [ + "object", + "null" + ], + "properties": { + "discountType": { + "type": "string", + "enum": [ + "percentage", + "fixed" + ] + }, + "discountValue": { + "type": "number", + "minimum": 0 + } + }, + "required": [ + "discountType", + "discountValue" + ] }, - "address1": { - "description": "Primary street address line.", - "type": "string", - "maxLength": 255 + "usageLimit": { + "description": "Total redemption limit; null for unlimited.", + "type": [ + "number", + "null" + ] }, - "address2": { - "description": "Secondary address line (apartment, suite, etc.).", - "type": "string", - "maxLength": 255 + "usesPerCustomer": { + "description": "Per-customer redemption limit; null for unlimited.", + "type": [ + "number", + "null" + ] }, - "city": { - "description": "City name.", - "type": "string", - "maxLength": 255 + "expiresAt": { + "description": "Expiry timestamp (ISO 8601). Omit for a code that never expires.", + "type": "string" }, - "state": { - "description": "State or province code.", - "type": "string", - "maxLength": 255 + "active": { + "description": "Whether the code can be redeemed. Defaults to true.", + "type": "boolean" + } + } + }, + "BatchCreateCouponsRequest": { + "description": "Parameters for batch-generating unique coupon codes for an existing type.", + "type": "object", + "properties": { + "typeId": { + "description": "Coupon type the generated codes reference.", + "type": "string" }, - "zip": { - "description": "Postal or ZIP code.", - "type": "string", - "maxLength": 255 + "count": { + "description": "Number of codes to generate (max 500). Defaults to 1.", + "type": "integer", + "minimum": 1, + "maximum": 500 }, - "country": { - "description": "ISO 3166-1 alpha-2 country code.", - "type": "string", - "maxLength": 255 + "prefix": { + "description": "Optional code prefix. Defaults to \"CODE\".", + "type": "string" }, - "phone": { - "description": "Phone number.", - "type": "string", - "maxLength": 255 + "discountOverride": { + "description": "Overrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.", + "type": [ + "object", + "null" + ], + "properties": { + "discountType": { + "type": "string", + "enum": [ + "percentage", + "fixed" + ] + }, + "discountValue": { + "type": "number", + "minimum": 0 + } + }, + "required": [ + "discountType", + "discountValue" + ] }, - "email": { - "type": "string", - "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", - "maxLength": 255 + "usageLimit": { + "description": "Total redemption limit for every code; null for unlimited.", + "type": [ + "number", + "null" + ] }, - "isDefault": { - "description": "Whether this is the default address for the customer.", - "type": "boolean" + "usesPerCustomer": { + "description": "Per-customer redemption limit for every code; null for unlimited.", + "type": [ + "number", + "null" + ] }, - "isValidated": { - "description": "Whether this address has been validated by an address verification service.", - "type": "boolean" + "expiresAt": { + "description": "Expiry timestamp (ISO 8601) applied to every generated code.", + "type": "string" } }, "required": [ - "name", - "email", - "address1", - "city", - "state", - "zip", - "country" + "typeId" ] }, "ErrorResponse": { diff --git a/api/preview-order.html b/api/preview-order.html index e09e2ec..d3b93b3 100644 --- a/api/preview-order.html +++ b/api/preview-order.html @@ -60,6 +60,8 @@

    Request body

    shippingMethodobjectno estimateTokenstringno paymentMethodstringno + checkoutFlow"standard" | "express"noCheckout flow type. `express` identifies wallet or shortcut checkout flows. + entryPoint"cart" | "checkout" | "pdp"noPage or experience where checkout started. couponCodestringno giftMessagestringno customerTimezonestringno diff --git a/api/update-coupon-type.html b/api/update-coupon-type.html new file mode 100644 index 0000000..9d555cb --- /dev/null +++ b/api/update-coupon-type.html @@ -0,0 +1,150 @@ + + + + + Update a coupon type — Helix Commerce API + + + + + + + + + + + +
    +
    +
    +

    Coupons

    +

    Update a coupon type

    +

    PUT /{org}/sites/{site}/coupons/types/{typeId}

    +

    Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

    +

    Merges the request body into the existing coupon type. `id` and `createdAt` are immutable. Setting `country` clears `countries` (and vice versa); switching between the flat and product-list shapes clears the opposing fields. Switching to the flat shape requires both `discountType` and `discountValue`.

    +

    Required permissions: coupons:write

    +

    Path parameters

    +
    + + + + + +
    NameTypeRequiredDescription
    orgstringyesOrganization identifier.
    sitestringyesSite identifier.
    typeIdstringyesCoupon type identifier.
    +
    +

    Request headers

    +
    + + + + +
    NameTypeRequiredDescription
    AuthorizationstringyesBearer token. `Bearer <jwt>`.
    Content-TypestringyesMust be `application/json`.
    +
    +

    Request body

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeRequiredDescription
    namestringnoHuman-readable name.
    minimumOrderAmountnumbernoMinimum pre-discount subtotal required to apply. Defaults to 0.
    maximumDiscountAmountnumber | nullnoCap on the discount amount (percentage coupons); null for no cap.
    freeShippingbooleannoGrants free shipping when applied.
    includedShippingTypesstring[]noWhen set, free shipping applies only to these shipping method types.
    includedCategoriesstring[]noCategories the coupon applies to.
    excludedCategoriesstring[]noCategories excluded from the coupon.
    stackablebooleannoWhether the coupon stacks with cart-level auto pricing rules. Defaults to true.
    autoApplybooleannoApply automatically without manual code entry. Defaults to false.
    allowManualEntrybooleannoAllow the code to be entered manually at checkout. Defaults to true.
    defaultUsageLimitnumber | nullnoDefault total usage limit for codes of this type; null for unlimited.
    defaultUsesPerCodenumber | nullnoDefault per-code usage limit; null for unlimited.
    notesstringnoFree-form operator notes.
    countrystringnoSingle ISO 3166-1 alpha-2 country the coupon is valid in. Mutually exclusive with `countries`.
    countriesstring[]noISO 3166-1 alpha-2 countries the coupon is valid in. Mutually exclusive with `country`.
    localestringnoBCP-47 locale the coupon is scoped to.
    discountType"percentage" | "fixed"noWhether `discountValue` is a percentage or a fixed cash amount.
    discountValuenumbernoDiscount magnitude — a percentage (0–100) when `discountType` is "percentage", otherwise a cash amount. Defaults to 0.
    includedProducts[]noWhen non-empty, only these products count toward the coupon. Each entry is a path string or a `{ path, sku? }` object.
    excludedProducts[]noProducts excluded from the coupon. Each entry is a path string or a `{ path, sku? }` object.
    excludeDiscountedProductsbooleannoWhen true, apply only to full-price lines (regular price equals sale price).
    applyToSalePricebooleannoWhen false (default) the discount is computed against the regular price with cheaper-wins; when true it stacks on the current sale price.
    discountedProductsDiscountedProduct[]noPer-product absolute price overrides. Exact duplicates (same path, or same path + sku) are rejected.
    +
    +

    Response

    +

    200 The updated coupon type.

    +

    400 Validation failed (mutually exclusive fields, category overlap, invalid country/locale, incomplete flat discount).

    +
    + + + + + +
    FieldTypeRequiredDescription
    codestringyesMachine-readable error code.
    messagestringyesHuman-readable error message.
    errorsobject[]noPer-field validation failures.
    +
    +

    404 No coupon type with this id.

    +
    + + + + + + + +
    FieldTypeRequiredDescription
    codestringyesMachine-readable error code (also sent as the `x-error-code` header).
    messagestringyesHuman-readable error message (also sent as the `x-error` header).
    resourcestringnoThe resource type involved, when applicable.
    retryablebooleannoWhether the caller may retry the request.
    detailsobjectnoOptional structured detail.
    +
    +
    +
    +
    +
    PUT /{org}/sites/{site}/coupons/types/{typeId}
    +
    {
    +  "discountValue": 15
    +}
    +
    +
    +
    Response · 200
    +
    {
    +  "id": "summer-10",
    +  "name": "10% Off Summer",
    +  "discountType": "percentage",
    +  "discountValue": 15,
    +  "minimumOrderAmount": 50,
    +  "maximumDiscountAmount": 100,
    +  "freeShipping": false,
    +  "stackable": true,
    +  "createdAt": "2026-01-01T00:00:00.000Z",
    +  "updatedAt": "2026-01-01T00:00:00.000Z"
    +}
    +
    +
    +
    Response · 400
    +
    {
    +  "code": "validation_failed",
    +  "message": "invalid request",
    +  "errors": [
    +    {
    +      "path": "$.country",
    +      "message": "invalid country code"
    +    }
    +  ]
    +}
    +
    +
    +
    Response · 404
    +
    {
    +  "code": "not_found",
    +  "message": "coupon type not found",
    +  "resource": "coupon_type"
    +}
    +
    +
    +
    +
    + + diff --git a/api/update-coupon.html b/api/update-coupon.html new file mode 100644 index 0000000..a9d2ef5 --- /dev/null +++ b/api/update-coupon.html @@ -0,0 +1,147 @@ + + + + + Update a coupon code — Helix Commerce API + + + + + + + + + + + +
    +
    +
    +

    Coupons

    +

    Update a coupon code

    +

    PUT /{org}/sites/{site}/coupons/{code}

    +

    Base URL https://api.adobecommerce.live · Staging https://api-stage.adobecommerce.live

    +

    Merges the request body into the existing coupon. `code`, `typeId`, `usageCount`, and `createdAt` are immutable. A `discountOverride` is rejected when the referenced type is a product-list coupon.

    +

    Required permissions: coupons:write

    +

    Path parameters

    +
    + + + + + +
    NameTypeRequiredDescription
    orgstringyesOrganization identifier.
    sitestringyesSite identifier.
    codestringyesCoupon code (case-insensitive; normalized to uppercase).
    +
    +

    Request headers

    +
    + + + + +
    NameTypeRequiredDescription
    AuthorizationstringyesBearer token. `Bearer <jwt>`.
    Content-TypestringyesMust be `application/json`.
    +
    +

    Request body

    +
    + + + + + + + +
    FieldTypeRequiredDescription
    discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
    usageLimitnumber | nullnoTotal redemption limit; null for unlimited.
    usesPerCustomernumber | nullnoPer-customer redemption limit; null for unlimited.
    expiresAtstringnoExpiry timestamp (ISO 8601). Omit for a code that never expires.
    activebooleannoWhether the code can be redeemed. Defaults to true.
    +
    +

    Response

    +

    200 The updated coupon code.

    +
    + + + + + + + + + + + + +
    FieldTypeRequiredDescription
    codestringyesThe coupon code (case-insensitive; normalized to uppercase). Letters, digits, hyphens, underscores; max 64 chars.
    typeIdstringyesIdentifier of the coupon type this code draws its discount from.
    discountOverrideobject | nullnoOverrides the coupon type's flat discount for this code. Not allowed when the type is a product-list coupon.
    usageLimitnumber | nullnoTotal redemption limit; null for unlimited.
    usageCountintegernoTimes redeemed. Managed by the service; ignored on write.
    usesPerCustomernumber | nullnoPer-customer redemption limit; null for unlimited.
    expiresAtstringnoExpiry timestamp (ISO 8601). Omit for a code that never expires.
    activebooleannoWhether the code can be redeemed. Defaults to true.
    createdAtstringnoCreation timestamp (ISO 8601). Managed by the service.
    updatedAtstringnoLast-update timestamp (ISO 8601). Managed by the service.
    +
    +

    400 A discountOverride was set on a code of a product-list coupon type.

    +
    + + + + + +
    FieldTypeRequiredDescription
    codestringyesMachine-readable error code.
    messagestringyesHuman-readable error message.
    errorsobject[]noPer-field validation failures.
    +
    +

    404 No coupon with this code.

    +
    + + + + + + + +
    FieldTypeRequiredDescription
    codestringyesMachine-readable error code (also sent as the `x-error-code` header).
    messagestringyesHuman-readable error message (also sent as the `x-error` header).
    resourcestringnoThe resource type involved, when applicable.
    retryablebooleannoWhether the caller may retry the request.
    detailsobjectnoOptional structured detail.
    +
    +
    +
    +
    +
    PUT /{org}/sites/{site}/coupons/{code}
    +
    {
    +  "active": false
    +}
    +
    +
    +
    Response · 200
    +
    {
    +  "code": "SAVE10",
    +  "typeId": "summer-10",
    +  "expiresAt": "2027-01-01T00:00:00Z",
    +  "discountOverride": null,
    +  "usageLimit": null,
    +  "usageCount": 0,
    +  "usesPerCustomer": null,
    +  "active": false,
    +  "createdAt": "2026-01-01T00:00:00.000Z",
    +  "updatedAt": "2026-01-01T00:00:00.000Z"
    +}
    +
    +
    +
    Response · 400
    +
    {
    +  "code": "validation_failed",
    +  "message": "invalid request",
    +  "errors": [
    +    {
    +      "path": "$.discountOverride",
    +      "message": "not allowed for a product-list coupon type"
    +    }
    +  ]
    +}
    +
    +
    +
    Response · 404
    +
    {
    +  "code": "not_found",
    +  "message": "coupon not found",
    +  "resource": "coupon"
    +}
    +
    +
    +
    + + + diff --git a/docs/schema-reference.md b/docs/schema-reference.md index c5c7ff1..9b55cca 100644 --- a/docs/schema-reference.md +++ b/docs/schema-reference.md @@ -349,6 +349,8 @@ The full order request body used when placing an order. | `shippingMethod` | object | No | Shipping method selected by the customer from the estimate rates. Required for order preview. | | `estimateToken` | string | No | Estimate token from a prior order preview. Used to lock in estimates at order creation time. | | `paymentMethod` | string | No | Payment method identifier. | +| `checkoutFlow` | `standard` \| `express` | No | Checkout flow type. `express` identifies wallet or shortcut checkout flows. | +| `entryPoint` | `cart` \| `checkout` \| `pdp` | No | Page or experience where checkout started. | | `couponCode` | string | No | Coupon code applied to the order. | | `giftMessage` | string | No | Optional gift message to include with the order. Max 250 characters. max length 250 | | `customerTimezone` | string | No | IANA timezone captured from the shopper's browser at checkout. max length 100; pattern constrained | @@ -469,6 +471,8 @@ The relaxed order request used for previews and estimates. `customer` is optiona | `shippingMethod` | object | No | Shipping method selected by the customer from the estimate rates. Required for order preview. | | `estimateToken` | string | No | Estimate token from a prior order preview. Used to lock in estimates at order creation time. | | `paymentMethod` | string | No | Payment method identifier. | +| `checkoutFlow` | `standard` \| `express` | No | Checkout flow type. `express` identifies wallet or shortcut checkout flows. | +| `entryPoint` | `cart` \| `checkout` \| `pdp` | No | Page or experience where checkout started. | | `couponCode` | string | No | Coupon code applied to the order. | | `giftMessage` | string | No | Optional gift message to include with the order. Max 250 characters. max length 250 | | `customerTimezone` | string | No | IANA timezone captured from the shopper's browser at checkout. max length 100; pattern constrained |