{
  "openapi": "3.1.1",
  "info": {
    "title": "CodePersist Customer API",
    "description": "Manage products with an organisation API key. Lite or Premium is required. Changes create immutable versions; publication is explicit. Send Authorization: Bearer <key>.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.codepersist.com/"
    }
  ],
  "paths": {
    "/api/v1/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List products",
        "description": "Read-only access. Lists only your organisation's products. Follow nextOffset until it is null. Pagination is a live view; concurrent changes can shift pages. Use gtin to find a product after an uncertain create response. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1ListProducts",
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "description": "Number of results to skip, from 0 to 2147483546; omitted means 0. Use nextOffset from the previous page. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 2147483546,
              "minimum": 0,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum items per page, from 1 to 100; omitted means 50. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          },
          {
            "name": "gtin",
            "in": "query",
            "description": "Optional valid GTIN-8, GTIN-12, GTIN-13 or GTIN-14 filter with a correct check digit; surrounding whitespace is trimmed. Empty input is rejected. Compare resolverUrl as well when identifying a specific product.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionPageOfProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a product",
        "description": "Write access. Creates an unpublished product using the existing plan limits and resolver ownership rules. GTIN and the original resolver become immutable. A default-resolver product can later gain one permanent custom domain through the custom-domain operation, app or Excel import. Returns 201 with Location. After losing the response, search by GTIN and original resolver before retrying. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1CreateProduct",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductInput"
              },
              "example": {
                "name": "Ground coffee 250g",
                "gtin": "09506000134352",
                "destinationUrl": "https://brand.example/coffee"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get a product",
        "description": "Read-only access. Returns complete configuration, current version and publication/removal progress. Missing and foreign products both return 404. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1GetProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "Products"
        ],
        "summary": "Replace product configuration",
        "description": "Write access. GET the product, then send expectedVersionId, name, the complete resources object and barcode settings. Preserves the original resolver and any permanent custom-domain attachment, and appends an immutable version. Does not publish. Returns 409 if the reviewed version changed. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1ReplaceProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceProductInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Delete a disabled product",
        "description": "Write access. Permanently deletes an owned product only after the reviewed disable operation has completed and both tokens still match. Missing and foreign products both return 204 without changing another organisation's data. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1DeleteProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          },
          {
            "name": "expectedVersionId",
            "in": "query",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          },
          {
            "name": "expectedRemovalOperationId",
            "in": "query",
            "description": "The product's removalOperationId from your latest read. Prevents acting on an outdated disable operation. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "204": {
            "description": "No Content"
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/custom-domain": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Attach a custom domain to a product",
        "description": "Write access. Permanently attaches one already-connected active custom resolver to an enabled default-resolver product with no attachment. Supply the reviewed current version id and the resolver HTTPS origin. Returns 200 with a new current version and custom digitalLinkUrl; preserves the original resolverUrl and uses no additional product slot. Previews use the custom URL immediately. Publish the returned version separately to activate both addresses and generate new production artwork. Missing or foreign products return 404. Missing, foreign or unavailable domains return a generic 400. A second attachment returns 400 with product.customDomain.alreadyAssigned; stale versions or blocked lifecycle state return 409. No domain provisioning or management is performed. After an uncertain response, reread the product before retrying. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1AttachCustomDomain",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachCustomDomainInput"
              },
              "example": {
                "expectedVersionId": "11111111-1111-1111-1111-111111111111",
                "resolverUrl": "https://id.brand.example/"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/versions": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List product versions",
        "description": "Read-only access. Lists immutable versions newest first. Saving or restoring adds a version; it never rewrites history. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1ListVersions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of results to skip, from 0 to 2147483546; omitted means 0. Use nextOffset from the previous page. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 2147483546,
              "minimum": 0,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum items per page, from 1 to 100; omitted means 50. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionPageOfVersionDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/versions/{number}/restore": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Restore a product version",
        "description": "Write access. Copies the numbered historical content into a new current version while preserving any permanent custom-domain attachment. Supply the current version id, not the historical id. Publication remains a separate action. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1RestoreVersion",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          },
          {
            "name": "number",
            "in": "path",
            "description": "The historical version number to copy, from 1 to 9223372036854775807; distinct from the expected current version UUID. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "required": true,
            "schema": {
              "maximum": 9223372036854775807,
              "minimum": 1,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VersionInput"
              },
              "example": {
                "expectedVersionId": "11111111-1111-1111-1111-111111111111"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/publications": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List publication attempts",
        "description": "Read-only access. Lists safe publication outcomes newest first. A successful older attempt does not mean the current edited version is published. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1ListPublications",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of results to skip, from 0 to 2147483546; omitted means 0. Use nextOffset from the previous page. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 2147483546,
              "minimum": 0,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum items per page, from 1 to 100; omitted means 50. Use ASCII decimal digits without a sign, whitespace, fraction or exponent.",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionPageOfPublicationDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Publish a product",
        "description": "Write access. Publishes exactly the reviewed current version to its original and any attached custom resolver through the normal durable publication workflow. On timeout or failure, read the product and publication history before retrying; recovery may still complete. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1PublishProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VersionInput"
              },
              "example": {
                "expectedVersionId": "11111111-1111-1111-1111-111111111111"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/disable": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Disable a product",
        "description": "Write access. Queues removal from the resolver and returns 202 with a product Location to poll. Completion is asynchronous. Retains configuration, versions and artwork. Existing cooldown and plan rules apply. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1DisableProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/enable": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Enable a disabled product",
        "description": "Write access. Requires the completed disable operation token and available plan capacity. Returns the product as unpublished; publish it explicitly to restore resolver output. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1EnableProduct",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemovalInput"
              },
              "example": {
                "expectedRemovalOperationId": "22222222-2222-2222-2222-222222222222"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/disable/retry": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Retry failed product disabling",
        "description": "Write access. Replaces the reviewed failed disable operation with a new attempt and returns 202. Poll the product for its new operation token and status. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1RetryDisable",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemovalInput"
              },
              "example": {
                "expectedRemovalOperationId": "22222222-2222-2222-2222-222222222222"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/barcode-preview": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Preview product QR artwork",
        "description": "Read-only access. Returns temporary image/svg+xml for the reviewed current saved settings and digitalLinkUrl, including a custom-domain attachment before publication. Does not retain artwork and does not require publication. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1PreviewBarcode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VersionInput"
              },
              "example": {
                "expectedVersionId": "11111111-1111-1111-1111-111111111111"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "SVG image bytes.",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{id}/barcodes": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Generate production QR artwork",
        "description": "Write access. Requires the exact current published version and encodes that version's digitalLinkUrl. Retains an immutable SVG generation and returns 201 with its authenticated download URL and SHA-256 digest. Earlier retained artwork keeps its original encoded URL. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1GenerateBarcode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The product id returned by creation or listing; ownership always comes from the API key. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VersionInput"
              },
              "example": {
                "expectedVersionId": "11111111-1111-1111-1111-111111111111"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BarcodeDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/barcodes/{id}/svg": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Download production QR artwork",
        "description": "Read-only access. Downloads retained SVG bytes owned by your organisation. X-Content-SHA256 is the digest of those bytes; Content-Disposition supplies the filename. Foreign and missing generations return 404. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1DownloadBarcode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The retained barcode generation id returned by generation. Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "required": true,
            "schema": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "SVG image bytes.",
            "headers": {
              "X-Content-SHA256": {
                "description": "SHA-256 digest of the downloaded SVG bytes.",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Attachment disposition with the generated artwork filename.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/batch/publish": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Publish multiple products",
        "description": "Write access. Publishes 1–5 reviewed products in input order using the normal production workflow. Each item reports an HTTP status and optional safe code. Successes remain committed if another item fails; the batch is not transactional. Foreign items return 404 without affecting their owner. Read current state after an uncertain response. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1BatchPublish",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchPublishRequest"
              },
              "example": {
                "items": [
                  {
                    "productId": "33333333-3333-3333-3333-333333333333",
                    "expectedVersionId": "11111111-1111-1111-1111-111111111111"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "example": {
                  "items": [
                    {
                      "productId": "33333333-3333-3333-3333-333333333333",
                      "status": 200,
                      "code": null
                    }
                  ],
                  "stopped": false
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/batch/disable": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Disable multiple products",
        "description": "Write access. Disables 1–5 products through the normal batch workflow. Validates ownership of the complete selection before work; a foreign or missing product rejects the selection with 404. Per-item 202 means removal was queued; poll each product. An infrastructure error can end the HTTP request after earlier successes; read every product before retrying. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1BatchDisable",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchDisableRequest"
              },
              "example": {
                "productIds": [
                  "33333333-3333-3333-3333-333333333333"
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "example": {
                  "items": [
                    {
                      "productId": "33333333-3333-3333-3333-333333333333",
                      "status": 202,
                      "code": null
                    }
                  ],
                  "stopped": false
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/batch/enable": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Enable multiple products",
        "description": "Write access. Enables 1–5 products through the normal batch workflow using each completed removal token. Validates ownership of the complete selection before work. Successful items remain committed and unpublished. An infrastructure error can end the HTTP request after earlier successes; read every product before retrying. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1BatchEnable",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchEnableRequest"
              },
              "example": {
                "items": [
                  {
                    "productId": "33333333-3333-3333-3333-333333333333",
                    "expectedRemovalOperationId": "22222222-2222-2222-2222-222222222222"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "example": {
                  "items": [
                    {
                      "productId": "33333333-3333-3333-3333-333333333333",
                      "status": 200,
                      "code": null
                    }
                  ],
                  "stopped": false
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    },
    "/api/v1/products/batch/delete": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Delete multiple disabled products",
        "description": "Write access. Deletes 1–5 reviewed products through the normal batch workflow. Both version and completed removal tokens are required. Missing and foreign products return per-item 204 without changing foreign data. Successful deletions remain committed if another item fails. Use the exact documented camelCase property and query names. Unknown or duplicate JSON properties and unknown, repeated or empty query parameters return 400. JSON numbers must be number tokens, not quoted strings; booleans must be true or false. Required members must be present, including nullable members. Non-null fields and array elements cannot be null. UUID inputs use the 36-character hyphenated form, accept either hexadecimal letter case and cannot be all zeroes. JSON request bodies are limited to 256 KiB; oversized bodies return 413 and unsupported content types return 415. Operations without a request body reject supplied content.",
        "operationId": "CustomerV1BatchDelete",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchDeleteRequest"
              },
              "example": {
                "items": [
                  {
                    "productId": "33333333-3333-3333-3333-333333333333",
                    "expectedVersionId": "11111111-1111-1111-1111-111111111111",
                    "expectedRemovalOperationId": "22222222-2222-2222-2222-222222222222"
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Invalid input. Problem Details may include a field-specific errors object and a safe code.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "API key missing, invalid, expired, revoked, or no longer associated with its original organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Write permission or a Lite/Premium subscription is required.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The resource is missing or belongs to another organisation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "The reviewed version/removal changed, or a production lifecycle/quota rule prevents the action. Read current state before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "413": {
            "description": "The JSON request body exceeds 256 KiB.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "415": {
            "description": "Use a supported JSON Content-Type for operations that require a body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Organisation request budget exceeded. Wait for the Retry-After delay before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "minimum": 1,
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "example": {
                  "items": [
                    {
                      "productId": "33333333-3333-3333-3333-333333333333",
                      "status": 204,
                      "code": null
                    }
                  ],
                  "stopped": false
                }
              }
            }
          }
        },
        "security": [
          {
            "CustomerApiKey": [ ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AttachCustomDomainInput": {
        "required": [
          "expectedVersionId",
          "resolverUrl"
        ],
        "type": "object",
        "properties": {
          "expectedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "resolverUrl": {
            "type": "string",
            "description": "Required, non-null HTTPS origin of an already-connected, verified and active custom domain owned by your organisation. Use an ASCII hostname, including punycode where needed, with no user information, non-root path, query or fragment. The exact normalized origin, including its port, must match the connected domain. No domain ID is needed. Unlike creation, omission or null never selects a default.",
            "format": "uri"
          }
        },
        "additionalProperties": false,
        "description": "Permanently attaches one already-connected, verified and active custom resolver to an enabled product created on the default CodePersist resolver. Both expectedVersionId and resolverUrl are required and non-null. Saves a new version without another product slot; publish that returned version separately to activate both addresses. Does not provision, replace or remove a domain."
      },
      "BarcodeDocument": {
        "required": [
          "id",
          "versionId",
          "downloadUrl",
          "sha256"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "versionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "downloadUrl": {
            "type": "string",
            "description": "Relative authenticated download URL. Resolve against the API origin."
          },
          "sha256": {
            "type": "string",
            "description": "SHA-256 digest of the retained SVG bytes."
          }
        },
        "description": "A retained SVG generation. DownloadUrl is relative to the API origin and requires an organisation API key."
      },
      "BarcodeSettings": {
        "type": "object",
        "properties": {
          "errorCorrection": {
            "enum": [
              "L",
              "M",
              "Q",
              "H"
            ],
            "type": "string",
            "description": "Case-sensitive QR error correction string: L, M, Q or H. Omitted means M; null and numeric values are rejected.",
            "default": "M"
          },
          "xDimensionMillimetres": {
            "multipleOf": 0.001,
            "maximum": 0.990,
            "minimum": 0.396,
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": "number",
            "description": "QR module width as a JSON number, 0.396–0.990 millimetres in increments of 0.001. The value must be exactly representable as a decimal; excess precision is rejected rather than rounded. Exponents and trailing zeroes are accepted when exact. Omitted means 0.495; null and quoted numbers are rejected.",
            "format": "double",
            "default": 0.495
          }
        },
        "additionalProperties": false,
        "description": "Digital Link QR settings. Production output is SVG; physical dimensions are in millimetres."
      },
      "BatchDeleteRequest": {
        "required": [
          "items"
        ],
        "type": "object",
        "properties": {
          "items": {
            "maxItems": 5,
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductDeletionSelection"
            },
            "description": "Between one and five selections with distinct product IDs. Invalid or duplicate selections reject the whole request with 400 before work."
          }
        },
        "additionalProperties": false,
        "description": "Deletes 1–5 distinct products using both reviewed version and removal tokens. Missing and foreign products are treated as already absent."
      },
      "BatchDisableRequest": {
        "required": [
          "productIds"
        ],
        "type": "object",
        "properties": {
          "productIds": {
            "maxItems": 5,
            "minItems": 1,
            "uniqueItems": true,
            "type": "array",
            "items": {
              "maxLength": 36,
              "minLength": 36,
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
              "type": "string",
              "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
              "format": "uuid"
            },
            "description": "Between one and five selections with distinct product IDs. Invalid or duplicate selections reject the whole request with 400 before work."
          }
        },
        "additionalProperties": false,
        "description": "Disables 1–5 distinct owned products. Ownership of the complete selection is checked before work."
      },
      "BatchEnableRequest": {
        "required": [
          "items"
        ],
        "type": "object",
        "properties": {
          "items": {
            "maxItems": 5,
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductRemovalSelection"
            },
            "description": "Between one and five selections with distinct product IDs. Invalid or duplicate selections reject the whole request with 400 before work."
          }
        },
        "additionalProperties": false,
        "description": "Enables 1–5 distinct owned products with completed removal tokens. Ownership of the complete selection is checked before work."
      },
      "BatchItemResult": {
        "required": [
          "productId",
          "status"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "enum": [
              200,
              202,
              204,
              400,
              404,
              409,
              503,
              424
            ],
            "type": "integer",
            "description": "Per-product HTTP status meaning, independent of the outer HTTP 200 response. Inspect every item before considering the batch successful.",
            "format": "int32"
          },
          "code": {
            "type": [
              "null",
              "string"
            ],
            "description": "Optional stable, safe error code. No provider diagnostics or credentials are returned."
          }
        },
        "description": "A product outcome using HTTP status meanings: 200 enabled/published, 202 removal accepted, 204 deleted/absent, 400 invalid, 404 not found, 409 conflict, 503 uncertain failure, or 424 not attempted."
      },
      "BatchPublishRequest": {
        "required": [
          "items"
        ],
        "type": "object",
        "properties": {
          "items": {
            "maxItems": 5,
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductVersionSelection"
            },
            "description": "Between one and five selections with distinct product IDs. Invalid or duplicate selections reject the whole request with 400 before work."
          }
        },
        "additionalProperties": false,
        "description": "Publishes 1–5 distinct products with their reviewed current version ids. Each item is independent; successful publications remain committed."
      },
      "BatchResult": {
        "required": [
          "items"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchItemResult"
            }
          },
          "stopped": {
            "type": "boolean",
            "description": "True when processing stopped before all submitted items could be confirmed. Read current state before retrying.",
            "default": false
          }
        },
        "description": "Ordered outcomes for the submitted products. The HTTP envelope is 200; inspect each item's status and the stopped flag. Successful items are not rolled back."
      },
      "CollectionPageOfProductDocument": {
        "required": [
          "items",
          "nextOffset"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductDocument"
            }
          },
          "nextOffset": {
            "minimum": 0,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer"
            ],
            "description": "Pass this value as offset for the next page. Null means the collection has ended.",
            "format": "int32"
          }
        }
      },
      "CollectionPageOfPublicationDocument": {
        "required": [
          "items",
          "nextOffset"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicationDocument"
            }
          },
          "nextOffset": {
            "minimum": 0,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer"
            ],
            "description": "Pass this value as offset for the next page. Null means the collection has ended.",
            "format": "int32"
          }
        }
      },
      "CollectionPageOfVersionDocument": {
        "required": [
          "items",
          "nextOffset"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionDocument"
            }
          },
          "nextOffset": {
            "minimum": 0,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer"
            ],
            "description": "Pass this value as offset for the next page. Null means the collection has ended.",
            "format": "int32"
          }
        }
      },
      "CreateProductInput": {
        "required": [
          "name",
          "gtin",
          "destinationUrl"
        ],
        "type": "object",
        "properties": {
          "name": {
            "minLength": 1,
            "type": "string",
            "description": "Product name, trimmed by the service. Must contain 1–200 characters after trimming; whitespace-only names are rejected."
          },
          "gtin": {
            "type": "string",
            "description": "A valid GTIN-8, GTIN-12, GTIN-13 or GTIN-14 made of ASCII digits with a correct check digit. Surrounding whitespace is trimmed. Responses use the zero-padded 14-digit form. Immutable after creation."
          },
          "destinationUrl": {
            "type": "string",
            "description": "Absolute HTTP or HTTPS URL with a host and no user information; the normalized absolute URL may contain at most 2048 characters. Unicode destinations are supported.",
            "format": "uri"
          },
          "resolverUrl": {
            "type": [
              "null",
              "string"
            ],
            "description": "Original immutable HTTPS resolver origin with an ASCII hostname and no user information, non-root path, query or fragment. Use punycode for an internationalized hostname. A custom resolver must already belong to your organisation and be available. Omitted or null on creation selects the configured default. This field remains unchanged if the custom-domain operation, app or Excel import later attaches a custom domain.",
            "format": "uri"
          },
          "resources": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ResourceSet"
              }
            ]
          },
          "barcode": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BarcodeSettings"
              }
            ]
          }
        },
        "additionalProperties": false,
        "description": "Creates an unpublished product. name, gtin and destinationUrl are required and non-null. Omitted or null resolverUrl uses the default resolver; omitted or null resources creates the default product-page link; omitted or null barcode uses M at 0.495 mm. destinationUrl is validated even when resources is supplied; that graph then controls the saved destinations."
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ProductDeletionSelection": {
        "required": [
          "productId",
          "expectedVersionId",
          "expectedRemovalOperationId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "expectedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "expectedRemovalOperationId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's removalOperationId from your latest read. Prevents acting on an outdated disable operation. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "additionalProperties": false
      },
      "ProductDocument": {
        "required": [
          "id",
          "gtin",
          "resolverUrl",
          "digitalLinkUrl",
          "status",
          "currentVersion",
          "publishedVersionId",
          "publishedAtUtc",
          "removalOperationId"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "gtin": {
            "type": "string",
            "description": "A valid GTIN-8, GTIN-12, GTIN-13 or GTIN-14 made of ASCII digits with a correct check digit. Surrounding whitespace is trimmed. Responses use the zero-padded 14-digit form. Immutable after creation."
          },
          "resolverUrl": {
            "type": "string",
            "description": "Original immutable HTTPS resolver origin with an ASCII hostname and no user information, non-root path, query or fragment. Use punycode for an internationalized hostname. A custom resolver must already belong to your organisation and be available. Omitted or null on creation selects the configured default. This field remains unchanged if the custom-domain operation, app or Excel import later attaches a custom domain.",
            "format": "uri"
          },
          "digitalLinkUrl": {
            "type": "string",
            "description": "The GS1 Digital Link URL encoded by the current saved version's preview and production artwork. It changes when the custom-domain operation, app or Excel import permanently attaches a custom domain to a default-resolver product; resolverUrl still identifies the original origin. New production artwork requires publication, which updates both addresses. Earlier retained artwork keeps its original URL.",
            "format": "uri"
          },
          "status": {
            "enum": [
              "unpublished",
              "publishing",
              "published",
              "publishFailed",
              "disabling",
              "disabled",
              "disableFailed"
            ],
            "type": "string"
          },
          "currentVersion": {
            "$ref": "#/components/schemas/VersionDocument"
          },
          "publishedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": [
              "null",
              "string"
            ],
            "description": "The last successfully published version. May differ from currentVersion.id after an edit. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "publishedAtUtc": {
            "maxLength": 27,
            "minLength": 27,
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{6}Z$",
            "type": [
              "null",
              "string"
            ],
            "description": "Last successful publication instant in UTC, formatted yyyy-MM-dd'T'HH:mm:ss.ffffff'Z' with six fractional digits; null when no version has been published. Not a request field.",
            "format": "date-time",
            "readOnly": true
          },
          "removalOperationId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": [
              "null",
              "string"
            ],
            "description": "Opaque disable operation identifier. Echo it when enabling, retrying disabling or deleting. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "description": "An organisation-owned product with its current configuration and separate publication state. resolverUrl remains the original immutable origin; digitalLinkUrl follows the current saved version's artwork URL, including a permanent custom domain attached through POST /products/{id}/custom-domain, the app or Excel import. Editing does not change the published output until publication succeeds."
      },
      "ProductRemovalSelection": {
        "required": [
          "productId",
          "expectedRemovalOperationId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "expectedRemovalOperationId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's removalOperationId from your latest read. Prevents acting on an outdated disable operation. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "additionalProperties": false
      },
      "ProductVersionSelection": {
        "required": [
          "productId",
          "expectedVersionId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "expectedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "additionalProperties": false
      },
      "PublicationDocument": {
        "required": [
          "id",
          "versionId",
          "status",
          "startedAtUtc",
          "completedAtUtc"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "versionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "status": {
            "enum": [
              "inProgress",
              "succeeded",
              "failed"
            ],
            "type": "string"
          },
          "startedAtUtc": {
            "maxLength": 27,
            "minLength": 27,
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{6}Z$",
            "type": "string",
            "description": "Server-assigned publication start instant in UTC, formatted yyyy-MM-dd'T'HH:mm:ss.ffffff'Z' with six fractional digits. Not a request field.",
            "format": "date-time",
            "readOnly": true
          },
          "completedAtUtc": {
            "maxLength": 27,
            "minLength": 27,
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{6}Z$",
            "type": [
              "null",
              "string"
            ],
            "description": "Publication completion instant in UTC, formatted yyyy-MM-dd'T'HH:mm:ss.ffffff'Z' with six fractional digits; null while incomplete. Not a request field.",
            "format": "date-time",
            "readOnly": true
          }
        },
        "description": "One publication attempt. Provider details remain private; use the product to determine its currently published version."
      },
      "RemovalInput": {
        "required": [
          "expectedRemovalOperationId"
        ],
        "type": "object",
        "properties": {
          "expectedRemovalOperationId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's removalOperationId from your latest read. Prevents acting on an outdated disable operation. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "additionalProperties": false,
        "description": "Selects the disable operation returned by the product. A changed or incomplete operation is rejected with 409."
      },
      "ReplaceProductInput": {
        "required": [
          "expectedVersionId",
          "name",
          "resources",
          "barcode"
        ],
        "type": "object",
        "properties": {
          "expectedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "name": {
            "minLength": 1,
            "type": "string",
            "description": "Product name, trimmed by the service. Must contain 1–200 characters after trimming; whitespace-only names are rejected."
          },
          "resources": {
            "$ref": "#/components/schemas/ResourceSet"
          },
          "barcode": {
            "$ref": "#/components/schemas/BarcodeSettings"
          }
        },
        "additionalProperties": false,
        "description": "Replaces all editable configuration and appends a version, even if values are unchanged. Copy resources and barcode from GET, apply changes and send the current version id."
      },
      "ResourceLink": {
        "required": [
          "id",
          "slotKey",
          "url",
          "relations",
          "title",
          "mediaType",
          "languages",
          "context"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]{0,99}$(?![\\s\\S])",
            "type": "string",
            "description": "Stable local identifier. Non-null values use 1–100 lowercase ASCII letters, digits or hyphens, starting with a letter or digit; values are not trimmed."
          },
          "slotKey": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]{0,99}$(?![\\s\\S])",
            "type": [
              "null",
              "string"
            ],
            "description": "Required member containing the key of this link's saved resource topic, or null for a link outside slots. Non-null values use 1–100 lowercase ASCII letters, digits or hyphens, starting with a letter or digit; values are not trimmed."
          },
          "url": {
            "type": "string",
            "description": "Absolute HTTP or HTTPS URL with a host and no user information; the normalized absolute URL may contain at most 2048 characters. Unicode destinations are supported.",
            "format": "uri"
          },
          "relations": {
            "maxItems": 8,
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "description": "Absolute HTTP or HTTPS relation URI with a host and no user information, at most 300 characters after normalization. Supported gs1: aliases expand to https://ref.gs1.org/voc/: pip, allergenInfo, ingredientsInfo, nutritionalInfo, instructions, certificationInfo, safetyInfo, quickStartGuide, tutorial, consumerHandlingStorageInfo, recallStatus, registerProduct, serviceInfo, support and verificationService. Alias names are case-sensitive. The exact GS1 defaultLink and defaultLinkMulti URIs are reserved. Fragments are significant; exact canonical duplicates are removed.",
              "format": "uri"
            },
            "description": "Between one and eight descriptive relation URIs. Supported gs1: aliases are expanded and exact canonical duplicates are removed; fragments are significant."
          },
          "title": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string",
            "description": "Nonblank text with at most 200 characters before trimming. Stored without surrounding whitespace."
          },
          "mediaType": {
            "type": [
              "null",
              "string"
            ],
            "description": "Bare type/subtype, trimmed and stored in lowercase; no parameters or wildcards. Each component contains 1–127 characters, at most 255 overall. Type accepts ASCII letters, digits and underscore; subtype also accepts hyphen, plus and period. Slot hints are suggestions, with normalized duplicates removed. Required member; null means no media type is specified."
          },
          "languages": {
            "maxItems": 8,
            "minItems": 0,
            "type": "array",
            "items": {
              "type": "string",
              "description": "Trimmed two-letter language code with an optional two-letter region, for example en or en-CA; either letter case is accepted. Other language-tag forms are not supported."
            },
            "description": "Between zero and eight trimmed two-letter language codes, each optionally followed by a hyphen and two-letter region. Either letter case is accepted. Independent of the API caller's language."
          },
          "context": {
            "maxItems": 8,
            "minItems": 0,
            "type": "array",
            "items": {
              "type": "string",
              "description": "A context descriptor containing 1–100 characters after trimming; whitespace-only descriptors are rejected."
            },
            "description": "Between zero and eight context descriptors of 1–100 characters each after trimming. Preserve descriptors during replacement."
          }
        },
        "additionalProperties": false,
        "description": "A destination link with descriptive relation URIs, languages, media type and context. Every field must be present; slotKey and mediaType may be null. Relation identity includes its fragment."
      },
      "ResourceSet": {
        "required": [
          "defaultLinkId",
          "slots",
          "links",
          "allowAdditionalRelations",
          "hostedLandingPageEnabled"
        ],
        "type": "object",
        "properties": {
          "defaultLinkId": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]{0,99}$(?![\\s\\S])",
            "type": "string",
            "description": "The id of the link used as the default scan destination; must identify a link in this resource set. Non-null values use 1–100 lowercase ASCII letters, digits or hyphens, starting with a letter or digit; values are not trimmed."
          },
          "slots": {
            "maxItems": 16,
            "minItems": 0,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceSlot"
            },
            "description": "Between zero and sixteen saved resource topics and their rules, with unique keys. Preserve the complete collection during replacement."
          },
          "links": {
            "maxItems": 32,
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceLink"
            },
            "description": "Between one and thirty-two links with unique IDs, including the required product-page link. Preserve the complete collection during replacement."
          },
          "allowAdditionalRelations": {
            "type": "boolean",
            "description": "Whether links may exist outside the saved slots; the required product-page link is always allowed. Required boolean with no default."
          },
          "hostedLandingPageEnabled": {
            "type": "boolean",
            "description": "Whether scans display a hosted choice of the product's saved links."
          }
        },
        "additionalProperties": false,
        "description": "The complete set of product links and their saved topic rules. Preserve all fields from GET when replacing a product. Keep a link with id product-page and relation https://ref.gs1.org/voc/pip. Link IDs and slot keys must be unique. The default must identify a configured link; every slot reference must exist and include that slot's relation, and its link count must satisfy the saved bounds. These are CodePersist's supported resource rules, not a complete GS1 conformance claim."
      },
      "ResourceSlot": {
        "required": [
          "key",
          "relationUri",
          "label",
          "minimumLinks",
          "maximumLinks",
          "mediaTypeHints"
        ],
        "type": "object",
        "properties": {
          "key": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]{0,99}$(?![\\s\\S])",
            "type": "string",
            "description": "Stable local identifier. Non-null values use 1–100 lowercase ASCII letters, digits or hyphens, starting with a letter or digit; values are not trimmed."
          },
          "relationUri": {
            "type": "string",
            "description": "Absolute HTTP or HTTPS relation URI with a host and no user information, at most 300 characters after normalization. Supported gs1: aliases expand to https://ref.gs1.org/voc/: pip, allergenInfo, ingredientsInfo, nutritionalInfo, instructions, certificationInfo, safetyInfo, quickStartGuide, tutorial, consumerHandlingStorageInfo, recallStatus, registerProduct, serviceInfo, support and verificationService. Alias names are case-sensitive. The exact GS1 defaultLink and defaultLinkMulti URIs are reserved. Fragments are significant; exact canonical duplicates are removed.",
            "format": "uri"
          },
          "label": {
            "maxLength": 100,
            "minLength": 1,
            "type": "string",
            "description": "Nonblank text with at most 100 characters before trimming. Stored without surrounding whitespace."
          },
          "minimumLinks": {
            "maximum": 4,
            "minimum": 0,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": "integer",
            "description": "Integer literal from 0 to 4, without a decimal point or exponent. minimumLinks must not exceed maximumLinks, and the number of links assigned to the slot must fall within both bounds.",
            "format": "int32"
          },
          "maximumLinks": {
            "maximum": 4,
            "minimum": 0,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": "integer",
            "description": "Integer literal from 0 to 4, without a decimal point or exponent. minimumLinks must not exceed maximumLinks, and the number of links assigned to the slot must fall within both bounds.",
            "format": "int32"
          },
          "mediaTypeHints": {
            "maxItems": 8,
            "minItems": 0,
            "type": "array",
            "items": {
              "type": "string",
              "description": "Bare type/subtype, trimmed and stored in lowercase; no parameters or wildcards. Each component contains 1–127 characters, at most 255 overall. Type accepts ASCII letters, digits and underscore; subtype also accepts hyphen, plus and period. Slot hints are suggestions, with normalized duplicates removed."
            },
            "description": "Between zero and eight bare media-type suggestions. Normalized duplicates are removed. Links are not required to use one of the suggestions."
          }
        },
        "additionalProperties": false,
        "description": "A resource topic and the link rules saved with this product version. Preserve these rules when editing links."
      },
      "VersionDocument": {
        "required": [
          "id",
          "number",
          "name",
          "resources",
          "barcode",
          "basedOnVersionId",
          "createdAtUtc"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "Opaque identifier. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "number": {
            "maximum": 9223372036854775807,
            "minimum": 1,
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string",
            "description": "Product name, trimmed by the service. Must contain 1–200 characters after trimming; whitespace-only names are rejected."
          },
          "resources": {
            "$ref": "#/components/schemas/ResourceSet"
          },
          "barcode": {
            "$ref": "#/components/schemas/BarcodeSettings"
          },
          "basedOnVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": [
              "null",
              "string"
            ],
            "description": "The historical source copied by a restore, when applicable. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          },
          "createdAtUtc": {
            "maxLength": 27,
            "minLength": 27,
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{6}Z$",
            "type": "string",
            "description": "Server-assigned version creation instant in UTC, formatted yyyy-MM-dd'T'HH:mm:ss.ffffff'Z' with six fractional digits. Not a request field.",
            "format": "date-time",
            "readOnly": true
          }
        },
        "description": "One immutable product configuration. Use id as expectedVersionId for later writes; number selects a historical version to restore."
      },
      "VersionInput": {
        "required": [
          "expectedVersionId"
        ],
        "type": "object",
        "properties": {
          "expectedVersionId": {
            "maxLength": 36,
            "minLength": 36,
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
            "type": "string",
            "description": "The product's currentVersion.id from your latest read. A different current version causes 409. A nonzero UUID in hyphenated 36-character form; input hexadecimal letters may use either case. Responses use lowercase.",
            "format": "uuid"
          }
        },
        "additionalProperties": false,
        "description": "Selects the exact current version. A changed version is rejected with 409; reread before deciding whether to retry."
      }
    },
    "securitySchemes": {
      "CustomerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "CodePersist API key"
      }
    }
  },
  "tags": [
    {
      "name": "Products"
    }
  ]
}