{
  "components": {
    "schemas": {
      "AdjustmentReason": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "is_system": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "version": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "is_system",
          "version"
        ],
        "type": "object"
      },
      "Brand": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "version"
        ],
        "type": "object"
      },
      "Category": {
        "additionalProperties": false,
        "properties": {
          "depth": {
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "parent_id",
          "depth",
          "version"
        ],
        "type": "object"
      },
      "Customer": {
        "additionalProperties": false,
        "properties": {
          "address_1": {
            "type": [
              "string",
              "null"
            ]
          },
          "address_2": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "custom_field_1": {
            "type": [
              "string",
              "null"
            ]
          },
          "custom_field_2": {
            "type": [
              "string",
              "null"
            ]
          },
          "custom_field_3": {
            "type": [
              "string",
              "null"
            ]
          },
          "custom_field_4": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_code": {
            "type": "string"
          },
          "customer_group_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "date_of_birth": {
            "description": "YYYY-MM-DD, or null.",
            "type": [
              "string",
              "null"
            ]
          },
          "do_not_sell_share": {
            "description": "Read-only. Set only through the admin UI or a DSAR request, never through this API.",
            "type": "boolean"
          },
          "dont_email": {
            "type": "boolean"
          },
          "dont_sms": {
            "type": "boolean"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "enable_loyalty": {
            "type": "boolean"
          },
          "first_name": {
            "type": "string"
          },
          "gender": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "is_walk_in": {
            "description": "True for the retailer’s single system walk-in customer.",
            "type": "boolean"
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "mobile": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "on_account_limit": {
            "description": "The customer’s account credit limit. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "tax_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "zipcode": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "customer_group_id",
          "customer_code",
          "first_name",
          "last_name",
          "company_name",
          "email",
          "phone",
          "mobile",
          "website",
          "gender",
          "date_of_birth",
          "tax_id",
          "note",
          "address_1",
          "address_2",
          "city",
          "state",
          "zipcode",
          "country",
          "custom_field_1",
          "custom_field_2",
          "custom_field_3",
          "custom_field_4",
          "on_account_limit",
          "enable_loyalty",
          "dont_email",
          "dont_sms",
          "do_not_sell_share",
          "is_walk_in",
          "created_at",
          "updated_at",
          "version"
        ],
        "type": "object"
      },
      "CustomerGroup": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "version"
        ],
        "type": "object"
      },
      "ErrorEnvelope": {
        "additionalProperties": false,
        "properties": {
          "error": {
            "additionalProperties": false,
            "properties": {
              "code": {
                "description": "A machine-readable error code, e.g. VALIDATION_FAILED.",
                "enum": [
                  "UNAUTHORIZED",
                  "PLAN_REQUIRED",
                  "INSUFFICIENT_SCOPE",
                  "NOT_FOUND",
                  "VALIDATION_FAILED",
                  "CONFLICT",
                  "STALE_VERSION",
                  "RATE_LIMITED",
                  "IDEMPOTENCY_KEY_REUSED",
                  "IDEMPOTENCY_IN_PROGRESS",
                  "IMAGE_FETCH_FAILED",
                  "UNPROCESSABLE",
                  "INTERNAL",
                  "RETAILER_CANCELLED",
                  "RETAILER_SUSPENDED",
                  "RETAILER_NOT_FOUND",
                  "TRIAL_DECISION_REQUIRED",
                  "PLAN_USERS_EXCEEDED",
                  "RETAILER_PAUSED",
                  "PRODUCT_LIMIT_REACHED",
                  "NOT_STOCK_TRACKED",
                  "REASON_DIRECTION_MISMATCH",
                  "REASON_NOT_ALLOWED",
                  "INSUFFICIENT_STOCK",
                  "OUTLET_DELETED"
                ],
                "type": "string"
              },
              "fields": {
                "items": {
                  "$ref": "#/components/schemas/ErrorField"
                },
                "type": "array"
              },
              "message": {
                "description": "A plain-English sentence describing what went wrong.",
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ],
            "type": "object"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "ErrorField": {
        "additionalProperties": false,
        "properties": {
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "field",
          "message"
        ],
        "type": "object"
      },
      "InventoryBatchLineResult": {
        "additionalProperties": false,
        "properties": {
          "changed": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "delta": {
            "type": [
              "number",
              "null"
            ]
          },
          "on_hand": {
            "type": [
              "number",
              "null"
            ]
          },
          "outlet_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "previous": {
            "type": [
              "number",
              "null"
            ]
          },
          "product_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "replayed": {
            "description": "true only on an idempotency replay.",
            "type": "boolean"
          },
          "sku": {
            "description": "Echoed only when the line was given by sku.",
            "type": "string"
          }
        },
        "required": [
          "product_id",
          "outlet_id",
          "changed",
          "previous",
          "on_hand",
          "delta"
        ],
        "type": "object"
      },
      "InventoryLevel": {
        "additionalProperties": false,
        "properties": {
          "on_hand": {
            "description": "Current stock level. Up to 3 decimal places.",
            "type": "number"
          },
          "outlet_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "reorder_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "reorder_method": {
            "type": "string"
          },
          "reorder_point": {
            "type": [
              "number",
              "null"
            ]
          },
          "reorder_target": {
            "type": [
              "number",
              "null"
            ]
          },
          "version": {
            "description": "Delta-sync version, as a string (bigint).",
            "type": "string"
          }
        },
        "required": [
          "outlet_id",
          "on_hand",
          "reorder_method",
          "reorder_point",
          "reorder_amount",
          "reorder_target",
          "version"
        ],
        "type": "object"
      },
      "Outlet": {
        "additionalProperties": false,
        "properties": {
          "default_tax_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "timezone",
          "status",
          "default_tax_id",
          "version"
        ],
        "type": "object"
      },
      "PaymentType": {
        "additionalProperties": false,
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "enabled",
          "version"
        ],
        "type": "object"
      },
      "Product": {
        "additionalProperties": false,
        "properties": {
          "active": {
            "type": "boolean"
          },
          "brand_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "category_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "codes": {
            "items": {
              "$ref": "#/components/schemas/ProductCode"
            },
            "type": "array"
          },
          "components": {
            "items": {
              "$ref": "#/components/schemas/ProductComponent"
            },
            "type": "array"
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "dimension_unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "has_inventory": {
            "type": "boolean"
          },
          "has_variants": {
            "type": "boolean"
          },
          "height": {
            "type": [
              "number",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "image_thumb_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_composite": {
            "type": "boolean"
          },
          "is_gift_card": {
            "type": "boolean"
          },
          "length": {
            "type": [
              "number",
              "null"
            ]
          },
          "loyalty_amount": {
            "anyOf": [
              {
                "description": "The loyalty amount earned on sale. Integer minor units (cents).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "type": "string"
          },
          "purchase_account_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "retail_price": {
            "description": "The retail price. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "sales_account_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "sku": {
            "type": "string"
          },
          "suppliers": {
            "description": "Live supplier links for this product. Never carries supply_price; use the admin UI or an export for cost data.",
            "items": {
              "$ref": "#/components/schemas/ProductSupplier"
            },
            "type": "array"
          },
          "tags": {
            "description": "Tags attached to this product, with names.",
            "items": {
              "$ref": "#/components/schemas/ProductTag"
            },
            "type": "array"
          },
          "updated_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "variant_attributes": {
            "description": "Present on a variant parent product; empty on a variant child or an ordinary product.",
            "items": {
              "$ref": "#/components/schemas/ProductAttribute"
            },
            "type": "array"
          },
          "variant_options": {
            "items": {
              "$ref": "#/components/schemas/ProductVariantOption"
            },
            "type": "array"
          },
          "variant_parent_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change to this document: its own fields, and the addition, removal, or edit of a code, tag link, supplier link, variant option, variant attribute, or component, including when an attached tag or supplier is itself renamed. Use it to detect updates.",
            "type": "string"
          },
          "weight": {
            "type": [
              "number",
              "null"
            ]
          },
          "weight_unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "width": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "sku",
          "name",
          "description",
          "active",
          "is_gift_card",
          "has_inventory",
          "has_variants",
          "variant_parent_id",
          "is_composite",
          "brand_id",
          "category_id",
          "retail_price",
          "loyalty_amount",
          "sales_account_code",
          "purchase_account_code",
          "weight",
          "weight_unit",
          "length",
          "width",
          "height",
          "dimension_unit",
          "image_url",
          "image_thumb_url",
          "codes",
          "tags",
          "suppliers",
          "variant_options",
          "variant_attributes",
          "components",
          "created_at",
          "updated_at",
          "version"
        ],
        "type": "object"
      },
      "ProductAttribute": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "description": "The variant attribute's id. A variant child's variant_options reference it as attribute_id.",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "description": "The attribute name, for example Size or Colour.",
            "type": "string"
          },
          "position": {
            "description": "Display order among this product's variant attributes.",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          }
        },
        "required": [
          "id",
          "name",
          "position"
        ],
        "type": "object"
      },
      "ProductCode": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "code"
        ],
        "type": "object"
      },
      "ProductComponent": {
        "additionalProperties": false,
        "properties": {
          "product_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "quantity": {
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          }
        },
        "required": [
          "product_id",
          "quantity"
        ],
        "type": "object"
      },
      "ProductSupplier": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "description": "This supplier link's own id, not the supplier's id. Distinct from supplier_id below.",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "is_primary": {
            "description": "Whether this is the product's primary supplier.",
            "type": "boolean"
          },
          "supplier_code": {
            "description": "This retailer's own code for the product at this supplier, if set.",
            "type": [
              "string",
              "null"
            ]
          },
          "supplier_id": {
            "description": "The linked supplier's id.",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "supplier_name": {
            "description": "The supplier name as of this document.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "supplier_id",
          "supplier_name",
          "supplier_code",
          "is_primary"
        ],
        "type": "object"
      },
      "ProductTag": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "description": "The tag's own id, usable to reference it elsewhere.",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "description": "The tag name as of this document.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "type": "object"
      },
      "ProductVariantOption": {
        "additionalProperties": false,
        "properties": {
          "attribute_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "attribute_name": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        },
        "required": [
          "attribute_id",
          "attribute_name",
          "value"
        ],
        "type": "object"
      },
      "Sale": {
        "additionalProperties": false,
        "properties": {
          "adjustments": {
            "items": {
              "$ref": "#/components/schemas/SaleAdjustment"
            },
            "type": "array"
          },
          "cash_discount_total": {
            "description": "Total cash-discount adjustment. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "completed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "customer_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "discount_total": {
            "description": "Reporting total: line + order + promo discount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "discounts": {
            "items": {
              "$ref": "#/components/schemas/SaleDiscount"
            },
            "type": "array"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "line_count": {
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "line_discount_total": {
            "description": "The line-level part of discount_total. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "lines": {
            "items": {
              "$ref": "#/components/schemas/SaleLine"
            },
            "type": "array"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "outlet_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "paid_total": {
            "description": "Total tendered. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "parent_sale_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set on a refund: the original sale it refunds."
          },
          "payments": {
            "items": {
              "$ref": "#/components/schemas/SalePayment"
            },
            "type": "array"
          },
          "receipt_label": {
            "type": [
              "string",
              "null"
            ]
          },
          "receipt_number": {
            "anyOf": [
              {
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "register_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "rounding_total": {
            "description": "Total rounding adjustment. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "source": {
            "type": "string"
          },
          "staff_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The cashier who rang the sale."
          },
          "status": {
            "enum": [
              "open",
              "completed",
              "partially_refunded",
              "refunded",
              "voided"
            ],
            "type": "string"
          },
          "subtotal": {
            "description": "Already net of the line discount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "surcharge_total": {
            "description": "Total surcharge adjustment. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "tax_total": {
            "description": "Total tax charged. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "taxes": {
            "items": {
              "$ref": "#/components/schemas/SaleTax"
            },
            "type": "array"
          },
          "total": {
            "description": "The sale total. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "total_qty": {
            "description": "Decimal, 3 places. Sum of line quantities.",
            "type": "number"
          },
          "updated_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          },
          "voided_at": {
            "anyOf": [
              {
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "outlet_id",
          "register_id",
          "customer_id",
          "parent_sale_id",
          "status",
          "receipt_number",
          "receipt_label",
          "source",
          "note",
          "subtotal",
          "discount_total",
          "line_discount_total",
          "tax_total",
          "total",
          "paid_total",
          "surcharge_total",
          "cash_discount_total",
          "rounding_total",
          "line_count",
          "total_qty",
          "completed_at",
          "voided_at",
          "created_at",
          "updated_at",
          "version",
          "staff_id",
          "lines",
          "discounts",
          "adjustments",
          "taxes",
          "payments"
        ],
        "type": "object"
      },
      "SaleAdjustment": {
        "additionalProperties": false,
        "properties": {
          "amount": {
            "description": "Signed: positive for a surcharge, negative for a cash discount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "tax_amount": {
            "description": "The tax charged on this adjustment. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "tax_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "taxable": {
            "type": "boolean"
          },
          "type": {
            "enum": [
              "surcharge",
              "cash_discount",
              "rounding"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "label",
          "amount",
          "taxable",
          "tax_id",
          "tax_amount"
        ],
        "type": "object"
      },
      "SaleDiscount": {
        "additionalProperties": false,
        "properties": {
          "allocation_method": {
            "enum": [
              "across",
              "each"
            ],
            "type": "string"
          },
          "code": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "promotion_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "enum": [
              "manual_line",
              "manual_order",
              "promo",
              "coupon"
            ],
            "type": "string"
          },
          "target_line_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "target_type": {
            "enum": [
              "line_item",
              "entire_sale"
            ],
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "value": {
            "description": "Cents when value_type is fixed; basis points when percent.",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "value_type": {
            "enum": [
              "percent",
              "fixed"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "source",
          "value_type",
          "value",
          "allocation_method",
          "target_type",
          "target_line_id",
          "title",
          "code",
          "promotion_id"
        ],
        "type": "object"
      },
      "SaleLine": {
        "additionalProperties": false,
        "properties": {
          "discount_allocations": {
            "items": {
              "$ref": "#/components/schemas/SaleLineDiscountAllocation"
            },
            "type": "array"
          },
          "discount_total": {
            "description": "The total discount allocated to this line. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "list_price": {
            "anyOf": [
              {
                "description": "The snapshot catalog price. Integer, 4 decimal places (1.2345 = 12345).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "price_book_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "price_total": {
            "description": "The line total, net of the line discount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "product_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "quantity": {
            "description": "Decimal, 3 places. Negative on a refund line.",
            "type": "number"
          },
          "refunded_qty": {
            "description": "Decimal, 3 places. Cumulative quantity refunded against this line.",
            "type": "number"
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          },
          "source_sale_line_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "On a refund line, the original sale line it returns."
          },
          "tax_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "tax_rate": {
            "anyOf": [
              {
                "description": "The snapshot tax rate. Integer basis points (1/100 of a percent).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "tax_total": {
            "description": "The tax charged on this line. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "unit_discount": {
            "description": "The per-unit discount. Integer, 4 decimal places (1.2345 = 12345).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "unit_price": {
            "description": "The snapshot unit price. Integer, 4 decimal places (1.2345 = 12345).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          }
        },
        "required": [
          "id",
          "product_id",
          "product_name",
          "sku",
          "quantity",
          "unit_price",
          "list_price",
          "unit_discount",
          "price_total",
          "discount_total",
          "tax_id",
          "tax_rate",
          "tax_total",
          "refunded_qty",
          "note",
          "source_sale_line_id",
          "price_book_id",
          "discount_allocations"
        ],
        "type": "object"
      },
      "SaleLineDiscountAllocation": {
        "additionalProperties": false,
        "properties": {
          "amount": {
            "description": "The amount of this line allocated to the discount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "discount_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          }
        },
        "required": [
          "discount_id",
          "amount"
        ],
        "type": "object"
      },
      "SalePayment": {
        "additionalProperties": false,
        "properties": {
          "amount": {
            "description": "The tender amount. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "amount_tendered": {
            "anyOf": [
              {
                "description": "Cash only: the amount physically handed over. Integer minor units (cents).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "card_brand": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "entry_mode": {
            "anyOf": [
              {
                "enum": [
                  "chip",
                  "contactless",
                  "swipe",
                  "manual",
                  "tap_to_pay"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "gift_card_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "last4": {
            "type": [
              "string",
              "null"
            ]
          },
          "payment_type_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "refunded_amount": {
            "description": "The cumulative amount refunded against this tender. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "status": {
            "enum": [
              "pending",
              "processing",
              "authorized",
              "captured",
              "voided",
              "refunded",
              "partially_refunded",
              "failed",
              "cancelled"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "payment_type_id",
          "amount",
          "amount_tendered",
          "status",
          "card_brand",
          "last4",
          "entry_mode",
          "gift_card_id",
          "refunded_amount",
          "created_at"
        ],
        "type": "object"
      },
      "SaleTax": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "rate": {
            "description": "The snapshot tax rate. Integer basis points (1/100 of a percent).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "tax_amount": {
            "description": "The tax charged at this rate. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "tax_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "taxable_amount": {
            "description": "The amount this rate was applied to. Integer minor units (cents).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          }
        },
        "required": [
          "id",
          "tax_id",
          "name",
          "rate",
          "taxable_amount",
          "tax_amount"
        ],
        "type": "object"
      },
      "SetInventoryResult": {
        "additionalProperties": false,
        "properties": {
          "adjustment_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "changed": {
            "type": "boolean"
          },
          "delta": {
            "type": "number"
          },
          "movement_id": {
            "anyOf": [
              {
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "on_hand": {
            "type": "number"
          },
          "previous": {
            "type": "number"
          }
        },
        "required": [
          "changed",
          "previous",
          "on_hand",
          "delta",
          "adjustment_id",
          "movement_id"
        ],
        "type": "object"
      },
      "StockAdjustmentResult": {
        "additionalProperties": false,
        "properties": {
          "adjustment_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "movement_id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "on_hand": {
            "type": "number"
          }
        },
        "required": [
          "adjustment_id",
          "movement_id",
          "on_hand"
        ],
        "type": "object"
      },
      "Store": {
        "additionalProperties": false,
        "properties": {
          "currency": {
            "type": "string"
          },
          "domain_prefix": {
            "type": "string"
          },
          "store_name": {
            "type": "string"
          },
          "tax_inclusive": {
            "type": "boolean"
          }
        },
        "required": [
          "store_name",
          "domain_prefix",
          "currency",
          "tax_inclusive"
        ],
        "type": "object"
      },
      "Supplier": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "version"
        ],
        "type": "object"
      },
      "SupplierDetail": {
        "additionalProperties": false,
        "properties": {
          "billing_address_1": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_address_2": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_city": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_country": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_fax": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_state": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing_zipcode": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "default_markup": {
            "anyOf": [
              {
                "description": "The default markup applied to this supplier’s products. Integer basis points (1/100 of a percent).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "shipping_address_1": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_address_2": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_city": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_country": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_fax": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_state": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipping_zipcode": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "default_markup",
          "billing_first_name",
          "billing_last_name",
          "billing_phone",
          "billing_email",
          "billing_fax",
          "billing_address_1",
          "billing_address_2",
          "billing_city",
          "billing_state",
          "billing_zipcode",
          "billing_country",
          "shipping_first_name",
          "shipping_last_name",
          "shipping_phone",
          "shipping_email",
          "shipping_fax",
          "shipping_address_1",
          "shipping_address_2",
          "shipping_city",
          "shipping_state",
          "shipping_zipcode",
          "shipping_country",
          "created_at",
          "updated_at",
          "version"
        ],
        "type": "object"
      },
      "Tag": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "version"
        ],
        "type": "object"
      },
      "Tax": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "rate": {
            "description": "The tax rate. Integer basis points (1/100 of a percent).",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          "version": {
            "description": "Opaque delta-sync version. Increases with every change; use it to detect updates.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "rate",
          "version"
        ],
        "type": "object"
      },
      "Tombstone": {
        "additionalProperties": false,
        "properties": {
          "deleted_at": {
            "description": "ISO-8601 timestamp of the deletion.",
            "type": "string"
          },
          "id": {
            "description": "The id of the deleted resource.",
            "type": "string"
          },
          "version": {
            "description": "The delta-sync version this tombstone was recorded at.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "deleted_at",
          "version"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "scheme": "bearer",
        "type": "http"
      },
      "oauth2": {
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://admin.oletapp.com/oauth/authorize",
            "refreshUrl": "https://api.oletapp.com/oauth/token",
            "scopes": {
              "catalog:read": "View your catalog, including products, prices, categories, brands, tags and suppliers.",
              "catalog:write": "Create, update and delete products, brands, categories, tags and suppliers in your catalog.",
              "customers:read": "View your customers. Includes names, emails and phone numbers.",
              "customers:write": "Create and update customer records, and permanently erase a customer's personal details. Erasure cannot be undone.",
              "inventory:read": "View stock levels across your outlets.",
              "inventory:write": "Adjust stock levels across your outlets.",
              "sales:read": "View your completed sales and refunds."
            },
            "tokenUrl": "https://api.oletapp.com/oauth/token"
          }
        },
        "type": "oauth2"
      }
    }
  },
  "info": {
    "description": "## Authentication\n\nAuthenticate with an API key or with OAuth. Access tokens last 1 hour. Refresh tokens do not rotate.\nA key or connection unused for 90 days stops working. Every path starts with the store prefix,\ngiven in the response from /me and in the token response's api_base_url.\n\n## Money\n\nAmounts are integer cents. A sale line's list_price, unit_price and unit_discount are integers\nwith 4 decimal places (1.2345 = 12345). Rates are integer basis points (1/100 of a percent).\nSaleDiscount.value is cents when value_type is fixed and basis points when value_type is percent.\n\n## Quantities\n\nQuantities are JSON numbers with up to 3 decimal places. A value with more decimal places is\nrejected with a validation error, not rounded.\n\n## Pagination and polling\n\nList endpoints take limit, cursor and order, and return next_cursor and has_more. Store the last\nnon-null next_cursor and pass it back as cursor to poll for changes. A page with no rows returns\nnext_cursor: null, so keep the cursor you already have. A cursor is opaque: pass it back byte for\nbyte as you received it. A cursor the server cannot read is rejected with a 400 VALIDATION_FAILED\nrather than silently restarting you at the first page. Pass include_deleted=true to also\nreceive deleted rows back as tombstones.\n\n## Idempotency\n\nIdempotency-Key is required on the stock adjustment and stock batch endpoints, and optional\nelsewhere. A retry with the same key and the same body replays the first response. A retry with\nthe same key and a different body answers IDEMPOTENCY_KEY_REUSED.\n\n## Errors\n\nEvery error response is an envelope: {error: {code, message, fields?}}. See the ErrorEnvelope\nschema below for the full list of codes.",
    "title": "Olet API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/brands": {
      "get": {
        "description": "Cursor-paginated: pass the previous response's `next_cursor` back as `cursor` to fetch the next page. Soft-deleted brands are omitted unless `include_deleted=true`, which only pairs with the default ascending `order`.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "brands.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Brand"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List brands"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "List brands",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "post": {
        "description": "Duplicate names (by slug) are refused with `409 CONFLICT`. An empty-slug name (no letters or numbers) is refused with `400 VALIDATION_FAILED`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "brands.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Brand"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a brand"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Create a brand",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/brands/{id}": {
      "delete": {
        "description": "Soft-deletes the brand and nulls `brand_id` on every product that referenced it, in one transaction, matching the behaviour of the admin app.\n\n- Because a product row that changes gets a new `version`, deleting a brand used by many products re-versions all of them at once, and they will all reappear in the caller's next delta-sync poll.\n\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted.\n\n**Requires scope:** `catalog:write`",
        "operationId": "brands.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a brand"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Delete a brand",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      },
      "get": {
        "description": "The shape is identical to one element of `brands.list`. A foreign, unknown or soft-deleted id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "brands.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Brand"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a brand"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "Get a brand",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "patch": {
        "description": "A rename recomputes the uniqueness slug. Renaming onto another live brand is refused with `409 CONFLICT`. A foreign or unknown id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "brands.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Brand"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a brand"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Update a brand",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/categories": {
      "get": {
        "description": "Cursor-paginated: pass the previous response's `next_cursor` back as `cursor` to fetch the next page. Soft-deleted categories are omitted unless `include_deleted=true`, which only pairs with the default ascending `order`.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "categories.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Category"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List product categories"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "List product categories",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "post": {
        "description": "A missing or foreign `parent_id` is refused with `404 NOT_FOUND`. Nesting under a system category, or under a parent already at maximum depth, is refused with `400 VALIDATION_FAILED`. Duplicate names are allowed.\n\n**Requires scope:** `catalog:write`",
        "operationId": "categories.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  },
                  "parent_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Category"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a category"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Create a category",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/categories/{id}": {
      "delete": {
        "description": "Soft-deletes the category and reassigns every product in it to the system \"Other Products\" category, in one transaction, matching the behaviour of the admin app.\n\n- Every reassigned product gets a new `version` and reappears in the caller's next delta-sync poll.\n\n- `409 CONFLICT`: the category is a system category.\n- `409 CONFLICT`: the category is the reserved `gift-cards` category.\n- `409 CONFLICT`: the category has live subcategories.\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted.\n\n**Requires scope:** `catalog:write`",
        "operationId": "categories.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a category"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Delete a category",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      },
      "get": {
        "description": "The shape is identical to one element of `categories.list`. A foreign, unknown or soft-deleted id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "categories.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Category"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a category"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "Get a category",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "patch": {
        "description": "`parent_id` is immutable: the strict schema refuses it in the body, matching the admin app. A foreign or unknown id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "categories.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Category"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a category"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Update a category",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/customers": {
      "get": {
        "description": "A delta-sync polling list: poll with the returned `next_cursor` to see only what changed.\n\nFilter by exact `email` (case-insensitive), `phone`, or `customer_code`. The walk-in system customer is included, flagged `is_walk_in`.\n\n**Requires scope:** `customers:read`",
        "operationId": "customers.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "Exact email match (case-insensitive).",
            "in": "query",
            "name": "email",
            "schema": {
              "description": "Exact email match (case-insensitive).",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "description": "Exact phone match.",
            "in": "query",
            "name": "phone",
            "schema": {
              "description": "Exact phone match.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "description": "Exact customer_code match.",
            "in": "query",
            "name": "customer_code",
            "schema": {
              "description": "Exact customer_code match.",
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "anyOf": [
                          {
                            "$ref": "#/components/schemas/Customer"
                          },
                          {
                            "$ref": "#/components/schemas/Tombstone"
                          }
                        ]
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List customers"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:read"
            ]
          }
        ],
        "summary": "List customers",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:read"
      },
      "post": {
        "description": "A missing `customer_code` is generated.\n\n`do_not_sell_share` cannot be set here; it is read-only, set only through the admin UI or a DSAR request. `on_account_limit` cannot be set here either (naming it is `400 VALIDATION_FAILED`); on-account sales are not built yet, though a response still carries the field.\n\n**Requires scope:** `customers:write`",
        "operationId": "customers.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "company_name": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "custom_field_1": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_2": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_3": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_4": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "customer_code": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "customer_group_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "date_of_birth": {
                    "anyOf": [
                      {
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dont_email": {
                    "type": "boolean"
                  },
                  "dont_sms": {
                    "type": "boolean"
                  },
                  "email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enable_loyalty": {
                    "type": "boolean"
                  },
                  "first_name": {
                    "maxLength": 100,
                    "minLength": 1,
                    "type": "string"
                  },
                  "gender": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mobile": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "note": {
                    "anyOf": [
                      {
                        "maxLength": 2000,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "tax_id": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "website": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "first_name"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a customer"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:write"
            ]
          }
        ],
        "summary": "Create a customer",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:write"
      }
    },
    "/customers/groups": {
      "get": {
        "description": "Cursor-paginated: pass the previous response's `next_cursor` back as `cursor` to fetch the next page. Soft-deleted groups are omitted unless `include_deleted=true`, which only pairs with the default ascending `order`.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `customers:read`",
        "operationId": "customer_groups.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/CustomerGroup"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List customer groups"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:read"
            ]
          }
        ],
        "summary": "List customer groups",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:read"
      }
    },
    "/customers/{id}": {
      "delete": {
        "description": "Permanently erases the customer's personal details. This cannot be undone.\n\n- Sets `deleted_at` and scrubs PII (name, email, phone, address and the rest).\n- Scrubs `customer_code` too, replaced by a `deleted+<id>` placeholder, so a customer can no longer be looked up by the code you created them with.\n- Bumps `version` so the tombstone reaches the next delta-sync poll.\n- Sale history survives: every past sale still resolves, shown against the anonymized customer.\n\n- `409 CONFLICT`: the walk-in system customer cannot be deleted.\n- `404 NOT_FOUND`: a foreign, unknown, or already-deleted id.\n\n**Requires scope:** `customers:write`",
        "operationId": "customers.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a customer"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:write"
            ]
          }
        ],
        "summary": "Delete a customer",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:write"
      },
      "get": {
        "description": "The full customer document, including `do_not_sell_share`, the consent flag `customers.list` also carries on each row.\n\n**Requires scope:** `customers:read`",
        "operationId": "customers.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a customer"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:read"
            ]
          }
        ],
        "summary": "Get a customer",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:read"
      },
      "patch": {
        "description": "`dont_email`/`dont_sms` are writable (opt-out only, same semantics as the admin PATCH).\n\n`do_not_sell_share` is read-only; naming it in the request body is refused with `400` (the schema is strict and does not accept it). `on_account_limit` is refused the same way; on-account sales are not built yet, though a response still carries the field.\n\n**Requires scope:** `customers:write`",
        "operationId": "customers.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "company_name": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "custom_field_1": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_2": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_3": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "custom_field_4": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "customer_code": {
                    "maxLength": 100,
                    "minLength": 1,
                    "type": "string"
                  },
                  "customer_group_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "date_of_birth": {
                    "anyOf": [
                      {
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dont_email": {
                    "type": "boolean"
                  },
                  "dont_sms": {
                    "type": "boolean"
                  },
                  "email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enable_loyalty": {
                    "type": "boolean"
                  },
                  "first_name": {
                    "maxLength": 100,
                    "minLength": 1,
                    "type": "string"
                  },
                  "gender": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mobile": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "note": {
                    "anyOf": [
                      {
                        "maxLength": 2000,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "tax_id": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "website": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a customer"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "customers:write"
            ]
          }
        ],
        "summary": "Update a customer",
        "tags": [
          "Customers"
        ],
        "x-olet-scope": "customers:write"
      }
    },
    "/inventory/adjustment-reasons": {
      "get": {
        "description": "Includes the read-only system API reasons (\"Stock set via API\") so merchants recognise them in reports.\n\n- Unpaginated: there is no cursor, no `next_cursor` value, and no `version` column on `adjustment_reason`. A store has only a handful of reasons.\n\n**Requires scope:** `inventory:read`",
        "operationId": "adjustment_reasons.list",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/AdjustmentReason"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List enabled stock adjustment reasons"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "inventory:read"
            ]
          }
        ],
        "summary": "List enabled stock adjustment reasons",
        "tags": [
          "Inventory"
        ],
        "x-olet-scope": "inventory:read"
      }
    },
    "/inventory/adjustments": {
      "post": {
        "description": "The same rule logic as the admin stock adjustment: direction comes from the reason, and the write is floored at zero.\n\n- Exactly one of `product_id` or `sku` is required. `sku` matches `product.sku` case-insensitively among live products only, and never a barcode (`product_code`).\n- `Idempotency-Key` is REQUIRED: a relative delta replayed without one would double-count.\n\n- `400 VALIDATION_FAILED`: neither or both of `product_id`/`sku` were given.\n- `404 NOT_FOUND`: the `sku` does not match a live product.\n- `422 INSUFFICIENT_STOCK`: the adjustment would take stock below zero.\n- `422 REASON_NOT_ALLOWED`: the reason is a system reason or is turned off. A reason must be enabled and must not be a system reason.\n- `422 OUTLET_DELETED`: the outlet has been deleted.\n\n`unit_cost` (integer cents, optional) is the cost of the units added; it is blended into the outlet's average cost. Leave it out to keep the current average. It is ignored when stock does not go up.\n\n**Requires scope:** `inventory:write`",
        "operationId": "inventory_adjustments.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "note": {
                    "anyOf": [
                      {
                        "maxLength": 2000,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "occurred_on": {
                    "anyOf": [
                      {
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "outlet_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "product_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "quantity": {
                    "type": "number"
                  },
                  "reason_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "sku": {
                    "maxLength": 100,
                    "minLength": 1,
                    "type": "string"
                  },
                  "unit_cost": {
                    "anyOf": [
                      {
                        "maximum": 900719925474,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "outlet_id",
                  "reason_id",
                  "quantity"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/StockAdjustmentResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Adjust a product's stock level by a relative quantity, with a reason"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "inventory:write"
            ]
          }
        ],
        "summary": "Adjust a product's stock level by a relative quantity, with a reason",
        "tags": [
          "Inventory"
        ],
        "x-olet-scope": "inventory:write"
      }
    },
    "/inventory/batch": {
      "post": {
        "description": "Each line names exactly one of `set` (absolute, same rules as `PUT /products/{id}/inventory/{outlet_id}`) or `adjust` (relative, same rules as `POST /inventory/adjustments`), and exactly one of `product_id` or `sku`.\n\n- `sku` matches `product.sku` case-insensitively among live products only, never a barcode. Every `sku` in the batch is resolved in ONE query before the transaction; an unknown `sku` fails the whole batch.\n- No duplicate `product_id`/`outlet_id` pair is allowed anywhere in the batch, including an `sku` line resolving to the same product/outlet as a `product_id` line.\n- Rows are locked in a stable order and the whole batch commits or nothing does: one bad line fails the whole request and writes zero rows.\n- `Idempotency-Key` is REQUIRED: a retried batch replayed without one could apply its relative `adjust` lines twice, moving stock again.\n\n- `400 VALIDATION_FAILED`: a line named zero or both of `set`/`adjust`, zero or both of `product_id`/`sku`, or duplicated a `product_id`/`outlet_id` pair.\n- `422 UNPROCESSABLE`: one or more `sku` values did not match a live product, naming `lines.N`.\n- `422 INSUFFICIENT_STOCK`: an `adjust` line would take stock below zero, naming `lines.N`.\n- `422 REASON_NOT_ALLOWED`: a line names a reason that is a system reason or is turned off, naming `lines.N`. A reason must be enabled and must not be a system reason.\n- `422 OUTLET_DELETED`: a line names an outlet that has been deleted. Nothing is written.\n\nA `set` or `adjust` line may carry `unit_cost` (integer cents, optional). On a `set` line it becomes the average cost for the outlet whatever the direction, including when on_hand is unchanged; left out, the current average is kept, or the supply price when there is none. On an `adjust` line it is blended into the average when stock goes up and ignored otherwise.\n\n**Requires scope:** `inventory:write`",
        "operationId": "inventory.batch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "lines": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "adjust": {
                          "additionalProperties": false,
                          "properties": {
                            "quantity": {
                              "type": "number"
                            },
                            "reason_id": {
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "type": "string"
                            },
                            "unit_cost": {
                              "anyOf": [
                                {
                                  "maximum": 900719925474,
                                  "minimum": 0,
                                  "type": "integer"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "reason_id",
                            "quantity"
                          ],
                          "type": "object"
                        },
                        "outlet_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "product_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "set": {
                          "additionalProperties": false,
                          "properties": {
                            "on_hand": {
                              "type": "number"
                            },
                            "reason_id": {
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                              "type": "string"
                            },
                            "unit_cost": {
                              "anyOf": [
                                {
                                  "maximum": 900719925474,
                                  "minimum": 0,
                                  "type": "integer"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "on_hand"
                          ],
                          "type": "object"
                        },
                        "sku": {
                          "maxLength": 100,
                          "minLength": 1,
                          "type": "string"
                        }
                      },
                      "required": [
                        "outlet_id"
                      ],
                      "type": "object"
                    },
                    "maxItems": 100,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "lines"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/InventoryBatchLineResult"
                      },
                      "type": "array"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Set or adjust stock levels for up to 100 product/outlet lines in one all-or-nothing request"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "inventory:write"
            ]
          }
        ],
        "summary": "Set or adjust stock levels for up to 100 product/outlet lines in one all-or-nothing request",
        "tags": [
          "Inventory"
        ],
        "x-olet-scope": "inventory:write"
      }
    },
    "/me": {
      "get": {
        "description": "A connection test: returns the store name and domain prefix this key belongs to, plus the scopes it was granted and its own id and name.\n\n**Requires scope:** `any`",
        "operationId": "meta.me",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "additionalProperties": false,
                      "properties": {
                        "domain_prefix": {
                          "description": "The retailer's domain prefix, e.g. https://api.oletapp.com/{domain_prefix}/v1.",
                          "type": "string"
                        },
                        "key": {
                          "additionalProperties": false,
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "name"
                          ],
                          "type": "object"
                        },
                        "scopes": {
                          "description": "The scopes this key or app connection was granted.",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "store_name": {
                          "description": "The retailer's store name.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "store_name",
                        "domain_prefix",
                        "scopes",
                        "key"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Check credentials and see which store this key belongs to"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Check credentials and see which store this key belongs to",
        "tags": [
          "Account"
        ],
        "x-olet-scope": "any"
      }
    },
    "/outlets": {
      "get": {
        "description": "Readable by any valid credential: it is reference data needed to interpret inventory and sale records, which are scoped to other permissions.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `any`",
        "operationId": "outlets.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Outlet"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List outlets"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List outlets",
        "tags": [
          "Store settings"
        ],
        "x-olet-scope": "any"
      }
    },
    "/payment-types": {
      "get": {
        "description": "Readable by any valid credential: it is reference data needed to interpret sale tenders, which are scoped to other permissions.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `any`",
        "operationId": "payment_types.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/PaymentType"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List payment types"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List payment types",
        "tags": [
          "Store settings"
        ],
        "x-olet-scope": "any"
      }
    },
    "/products": {
      "get": {
        "description": "A delta-sync polling list: poll with the returned `next_cursor` to see only what changed since the last page. Each row is the same full product document `products.get` returns: codes, tags, suppliers, variant options and attributes, and components, never a slimmer summary.\n\n- Filter by exact `sku`, `active`, or `variant_parent_id`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "products.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "Exact SKU or barcode match (case-insensitive).",
            "in": "query",
            "name": "sku",
            "schema": {
              "description": "Exact SKU or barcode match (case-insensitive).",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "active",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "variant_parent_id",
            "schema": {
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "anyOf": [
                          {
                            "$ref": "#/components/schemas/Product"
                          },
                          {
                            "$ref": "#/components/schemas/Tombstone"
                          }
                        ]
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List products"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "List products",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:read"
      },
      "post": {
        "description": "Creates a product, optionally with its nested codes, tags, suppliers, variant_attributes and components in the same atomic request.\n\n- Include `codes`, `tags`, `suppliers`, `variant_attributes` or `components` to create that collection alongside the product; omit one to create none of that kind.\n- tags are referenced by tag id; an unknown id is a 400.\n- supply_price is never accepted, neither on the product nor on a nested supplier.\n- variant_options is read-only and ignored if sent.\n- The write is atomic: an invalid entry in any collection creates nothing, not even the product.\n- image_url fetches the image once and imports it through the same pipeline as an admin upload; a fetch failure does not undo the product write: it answers 422 IMAGE_FETCH_FAILED with the created product in data.\n\n- `400 VALIDATION_FAILED`: a field failed validation, including a duplicate natural key within one collection, or a variant_attributes rule (more than 3 entries, a position outside 1 to 3, or a duplicate position).\n- `402 PRODUCT_LIMIT_REACHED`: the plan's product quota is reached.\n- `409 CONFLICT`: the sku is already in use, or a nested code or supplier link conflicts with an existing one.\n- `422 UNPROCESSABLE`: a codes, tags, suppliers or components cap was exceeded.\n- `422 IMAGE_FETCH_FAILED`: the product was created but the image could not be imported.\n\n**Requires scope:** `catalog:write`",
        "operationId": "products.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "active": {
                    "type": "boolean"
                  },
                  "brand_id": {
                    "anyOf": [
                      {
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "category_id": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "type": "string"
                          },
                          {
                            "const": "",
                            "type": "string"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "codes": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "type": {
                          "enum": [
                            "upc",
                            "isbn",
                            "itf",
                            "ean",
                            "jan",
                            "custom"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "type",
                        "code"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "components": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "product_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "quantity": {
                          "maximum": 9007199254740991,
                          "minimum": 1,
                          "type": "integer"
                        }
                      },
                      "required": [
                        "product_id",
                        "quantity"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "created_at": {},
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dimension_unit": {
                    "anyOf": [
                      {
                        "enum": [
                          "mm",
                          "cm",
                          "in",
                          "ft"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "has_inventory": {
                    "type": "boolean"
                  },
                  "has_variants": {
                    "type": "boolean"
                  },
                  "height": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "id": {},
                  "image_thumb_url": {},
                  "image_url": {
                    "anyOf": [
                      {
                        "format": "uri",
                        "maxLength": 2048,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Import the product image from this https URL (fetched once; the external URL is never stored). null or omitted leaves the current image untouched; this API cannot clear an existing image."
                  },
                  "is_composite": {
                    "type": "boolean"
                  },
                  "is_gift_card": {},
                  "length": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "loyalty_amount": {
                    "anyOf": [
                      {
                        "maximum": 900719925474,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  },
                  "purchase_account_code": {
                    "anyOf": [
                      {
                        "maxLength": 50,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "retail_price": {
                    "maximum": 900719925474,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "sales_account_code": {
                    "anyOf": [
                      {
                        "maxLength": 50,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sku": {
                    "type": "string"
                  },
                  "suppliers": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "is_primary": {
                          "type": "boolean"
                        },
                        "supplier_code": {
                          "anyOf": [
                            {
                              "maxLength": 100,
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "supplier_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "supplier_name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "supplier_id"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "tags": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "updated_at": {},
                  "variant_attributes": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "maxLength": 50,
                          "minLength": 1,
                          "type": "string"
                        },
                        "position": {
                          "maximum": 3,
                          "minimum": 1,
                          "type": "integer"
                        }
                      },
                      "required": [
                        "name",
                        "position"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "variant_options": {
                    "items": {},
                    "type": "array"
                  },
                  "variant_parent_id": {
                    "anyOf": [
                      {
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "weight": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "weight_unit": {
                    "anyOf": [
                      {
                        "enum": [
                          "g",
                          "kg",
                          "lb",
                          "oz"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "width": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name",
                  "retail_price"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a product"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Create a product",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/products/{id}": {
      "delete": {
        "description": "Soft-deletes the product.\n\n- `422 UNPROCESSABLE`: it is a gift card product.\n- `409 CONFLICT`: it is used as a composite component.\n- `409 CONFLICT`: it has active variant children.\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted.\n\n**Requires scope:** `catalog:write`",
        "operationId": "products.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a product"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Delete a product",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:write"
      },
      "get": {
        "description": "Returns the whole product document in one call: `codes`, `tags` (with names), `suppliers` (with `supplier_name`), `variant_options`, `variant_attributes`, and `components`. There are no separate sub-resource reads for any of these.\n\n- `variant_attributes` is populated on a variant parent and empty everywhere else; `variant_options` is the child side, populated only on a variant child.\n- `suppliers` carries the link's own `id` as well as `supplier_id`, and never `supply_price`: supplier cost is not exposed through this API.\n- `version` moves when any part of the document changes, including when an attached tag or supplier is itself renamed.\n\n- `404 NOT_FOUND`: the id is foreign, unknown, or deleted.\n\n**Requires scope:** `catalog:read`",
        "operationId": "products.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a product"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "Get a product",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:read"
      },
      "patch": {
        "description": "Updates a product, and replaces any nested collection included in the body.\n\n- Omitting `codes`, `tags`, `suppliers`, `variant_attributes` or `components` leaves that collection untouched; sending `[]` clears it.\n- tags are referenced by tag id; an unknown id is a 400.\n- supply_price is never accepted, neither on the product nor on a nested supplier.\n- variant_options is read-only and ignored if sent.\n- variant_attributes can only change while the product has no live variant children; once it does, a change is a 409.\n- The `version` a GET response returned can be sent back as the concurrency check, same as today's `expected_version`; sending both requires they agree.\n- The write is atomic: an invalid entry in any collection applies nothing, not even a scalar change.\n- image_url fetches the image once and imports it through the same pipeline as an admin upload; a fetch failure does not undo the update: it answers 422 IMAGE_FETCH_FAILED with the updated product in data. Gift card products can't be changed through this endpoint.\n\n- `400 VALIDATION_FAILED`: a field failed validation, `version` and `expected_version` disagree, or a variant_attributes rule (more than 3 entries, a position outside 1 to 3, or a duplicate position).\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted, or a referenced brand or category was not found.\n- `409 CONFLICT`: variant_attributes changed while the product has live variant children, or a nested code or supplier link conflicts with an existing one.\n- `409 STALE_VERSION`: `version`/`expected_version` did not match the product's current version.\n- `422 UNPROCESSABLE`: it is a gift card product, or a codes, tags, suppliers or components cap was exceeded.\n- `422 IMAGE_FETCH_FAILED`: the product was updated but the image could not be imported.\n\n**Requires scope:** `catalog:write`",
        "operationId": "products.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "active": {
                    "type": "boolean"
                  },
                  "brand_id": {
                    "anyOf": [
                      {
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "category_id": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "type": "string"
                          },
                          {
                            "const": "",
                            "type": "string"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "codes": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "type": {
                          "enum": [
                            "upc",
                            "isbn",
                            "itf",
                            "ean",
                            "jan",
                            "custom"
                          ],
                          "type": "string"
                        }
                      },
                      "required": [
                        "type",
                        "code"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "components": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "product_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "quantity": {
                          "maximum": 9007199254740991,
                          "minimum": 1,
                          "type": "integer"
                        }
                      },
                      "required": [
                        "product_id",
                        "quantity"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "created_at": {},
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dimension_unit": {
                    "anyOf": [
                      {
                        "enum": [
                          "mm",
                          "cm",
                          "in",
                          "ft"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "expected_version": {
                    "anyOf": [
                      {
                        "maximum": 9007199254740991,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "pattern": "^\\d+$",
                        "type": "string"
                      }
                    ]
                  },
                  "has_inventory": {
                    "type": "boolean"
                  },
                  "has_variants": {},
                  "height": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "id": {},
                  "image_thumb_url": {},
                  "image_url": {
                    "anyOf": [
                      {
                        "format": "uri",
                        "maxLength": 2048,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Import the product image from this https URL (fetched once; the external URL is never stored). null or omitted leaves the current image untouched; this API cannot clear an existing image."
                  },
                  "is_composite": {},
                  "is_gift_card": {},
                  "length": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "loyalty_amount": {
                    "anyOf": [
                      {
                        "maximum": 900719925474,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  },
                  "purchase_account_code": {
                    "anyOf": [
                      {
                        "maxLength": 50,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "retail_price": {
                    "maximum": 900719925474,
                    "minimum": 0,
                    "type": "integer"
                  },
                  "sales_account_code": {
                    "anyOf": [
                      {
                        "maxLength": 50,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sku": {},
                  "suppliers": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "is_primary": {
                          "type": "boolean"
                        },
                        "supplier_code": {
                          "anyOf": [
                            {
                              "maxLength": 100,
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "supplier_id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "supplier_name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "supplier_id"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "tags": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "updated_at": {},
                  "variant_attributes": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "maxLength": 50,
                          "minLength": 1,
                          "type": "string"
                        },
                        "position": {
                          "maximum": 3,
                          "minimum": 1,
                          "type": "integer"
                        }
                      },
                      "required": [
                        "name",
                        "position"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "variant_options": {
                    "items": {},
                    "type": "array"
                  },
                  "variant_parent_id": {},
                  "version": {
                    "anyOf": [
                      {
                        "maximum": 9007199254740991,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "pattern": "^\\d+$",
                        "type": "string"
                      }
                    ]
                  },
                  "weight": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "weight_unit": {
                    "anyOf": [
                      {
                        "enum": [
                          "g",
                          "kg",
                          "lb",
                          "oz"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "width": {
                    "anyOf": [
                      {
                        "maximum": 99999.99,
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a product"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Update a product",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/products/{id}/inventory": {
      "get": {
        "description": "Never includes `average_cost` or `total_cost`. Quantities are numbers, up to 3 decimal places.\n\n- `404 NOT_FOUND`: the product id is foreign, unknown, or deleted.\n\n**Requires scope:** `inventory:read`",
        "operationId": "inventory.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/InventoryLevel"
                      },
                      "type": "array"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List a product's stock levels, one row per live outlet"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "inventory:read"
            ]
          }
        ],
        "summary": "List a product's stock levels, one row per live outlet",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "inventory:read"
      }
    },
    "/products/{id}/inventory/{outlet_id}": {
      "put": {
        "description": "Loop-safe: the delta is computed server-side from the current level under a row lock, so sending the same `on_hand` twice writes nothing the second time (`changed: false`).\n\n- A supplied `reason_id` must match the computed direction, or leave it out to use the system \"Stock set via API\" reason.\n- `Idempotency-Key` is optional here: the write is already idempotent by construction.\n\n- `422 REASON_DIRECTION_MISMATCH`: the supplied `reason_id` does not match the computed direction.\n- `422 REASON_NOT_ALLOWED`: the supplied `reason_id` is a system reason or is turned off. A reason must be enabled and must not be a system reason.\n- `422 OUTLET_DELETED`: the outlet has been deleted.\n\n`unit_cost` (integer cents, optional) becomes the average cost for the outlet, whether stock goes up, down or stays the same. Leave it out to keep the current average, or the supply price when there is no average yet.\n\n**Requires scope:** `inventory:write`",
        "operationId": "inventory.set",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "note": {
                    "anyOf": [
                      {
                        "maxLength": 2000,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "on_hand": {
                    "type": "number"
                  },
                  "reason_id": {
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                    "type": "string"
                  },
                  "unit_cost": {
                    "anyOf": [
                      {
                        "maximum": 900719925474,
                        "minimum": 0,
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "on_hand"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SetInventoryResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Set a product's absolute stock level at one outlet"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "inventory:write"
            ]
          }
        ],
        "summary": "Set a product's absolute stock level at one outlet",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "inventory:write"
      }
    },
    "/products/{id}/variants": {
      "post": {
        "description": "Creates new product rows as children of the variant parent. Each variant names its own option combination explicitly; this is not a matrix expansion of the parent's attributes.\n\n- `attribute_id` in each option must belong to the parent.\n- Option combinations are deduped against the request and against existing children.\n- Capped at 200 children per product, all-or-nothing.\n- `supply_price` is never accepted.\n- Idempotent via `Idempotency-Key`, with every created id replayed.\n- Children are ordinary products afterwards, read, updated and deleted via `/products/{id}`.\n\n- `409 CONFLICT`: a duplicate option combination.\n\n**Requires scope:** `catalog:write`",
        "operationId": "product_variants.generate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "variants": {
                    "items": {
                      "additionalProperties": false,
                      "properties": {
                        "active": {
                          "type": "boolean"
                        },
                        "name": {
                          "maxLength": 255,
                          "minLength": 1,
                          "type": "string"
                        },
                        "options": {
                          "items": {
                            "properties": {
                              "attribute_id": {
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                                "type": "string"
                              },
                              "value": {
                                "maxLength": 100,
                                "minLength": 1,
                                "type": "string"
                              }
                            },
                            "required": [
                              "attribute_id",
                              "value"
                            ],
                            "type": "object"
                          },
                          "minItems": 1,
                          "type": "array"
                        },
                        "retail_price": {
                          "maximum": 900719925474,
                          "minimum": 1,
                          "type": "integer"
                        },
                        "sku": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "options"
                      ],
                      "type": "object"
                    },
                    "maxItems": 200,
                    "minItems": 1,
                    "type": "array"
                  }
                },
                "required": [
                  "variants"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      },
                      "type": "array"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Generate variant children for a variant parent product"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Generate variant children for a variant parent product",
        "tags": [
          "Products"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/sales": {
      "get": {
        "description": "A delta-sync polling list: poll with the returned `next_cursor` to see only what changed.\n\nExcludes open (parked) sales by default; `status=open` is refused. A refund is a sale carrying `parent_sale_id`. `include_deleted` is not applicable (sales are never deleted) and is refused if set.\n\n**Requires scope:** `sales:read`",
        "operationId": "sales.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "Defaults to every status except open (parked sales are register state, not returned by this API).",
            "in": "query",
            "name": "status",
            "schema": {
              "description": "Defaults to every status except open (parked sales are register state, not returned by this API).",
              "enum": [
                "completed",
                "partially_refunded",
                "refunded",
                "voided"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "outlet_id",
            "schema": {
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "customer_id",
            "schema": {
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "type": "string"
            }
          },
          {
            "description": "ISO-8601 datetime. Filters on completed_at.",
            "in": "query",
            "name": "completed_from",
            "schema": {
              "description": "ISO-8601 datetime. Filters on completed_at.",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
              "type": "string"
            }
          },
          {
            "description": "ISO-8601 datetime. Filters on completed_at.",
            "in": "query",
            "name": "completed_to",
            "schema": {
              "description": "ISO-8601 datetime. Filters on completed_at.",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
              "type": "string"
            }
          },
          {
            "description": "Filter to refunds of one original sale.",
            "in": "query",
            "name": "parent_sale_id",
            "schema": {
              "description": "Filter to refunds of one original sale.",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Sale"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List sales"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "sales:read"
            ]
          }
        ],
        "summary": "List sales",
        "tags": [
          "Sales"
        ],
        "x-olet-scope": "sales:read"
      }
    },
    "/sales/{id}": {
      "get": {
        "description": "Returns one sale in any non-open status, with its line items, payments and totals. A parked (open) sale reads as not found.\n\n- `404 NOT_FOUND`: the id is foreign, unknown, or names a parked sale.\n\n**Requires scope:** `sales:read`",
        "operationId": "sales.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Sale"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a sale"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "sales:read"
            ]
          }
        ],
        "summary": "Get a sale",
        "tags": [
          "Sales"
        ],
        "x-olet-scope": "sales:read"
      }
    },
    "/store": {
      "get": {
        "description": "Readable by any valid credential: it is reference data needed to interpret every other resource. Returns `store_name`, `domain_prefix` (the prefix on every API path and the OAuth token response's `api_base_url`), `currency`, and `tax_inclusive`.\n\n**Requires scope:** `any`",
        "operationId": "store.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Store"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get store settings"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get store settings",
        "tags": [
          "Account"
        ],
        "x-olet-scope": "any"
      }
    },
    "/suppliers": {
      "get": {
        "description": "Cursor-paginated: pass the previous response's `next_cursor` back as `cursor` to fetch the next page. Returns only `id`, `name` and `version`; call `suppliers.get` for billing and shipping contacts. Soft-deleted suppliers are omitted unless `include_deleted=true`, which only pairs with the default ascending `order`.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "suppliers.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Supplier"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List suppliers"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "List suppliers",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "post": {
        "description": "Accepts every field the admin create form accepts, including billing/shipping contacts and `default_markup` (basis points). Duplicate names are allowed.\n\n**Requires scope:** `catalog:write`",
        "operationId": "suppliers.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "billing_address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_fax": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_first_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "default_markup": {
                    "anyOf": [
                      {
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  },
                  "shipping_address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_fax": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_first_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SupplierDetail"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a supplier"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Create a supplier",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/suppliers/{id}": {
      "delete": {
        "description": "Soft-deletes the supplier and removes its link from every product that carried it, in one transaction, matching the behaviour of the admin app.\n\n- Removing the link is a change to each affected product, so its `version` bumps and it reappears in the caller's next delta-sync poll.\n- A purchase order that named this supplier keeps its `supplier_id`. That reference is not nulled, and is left pointing at the deleted row.\n\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted.\n\n**Requires scope:** `catalog:write`",
        "operationId": "suppliers.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a supplier"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Delete a supplier",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      },
      "get": {
        "description": "The full supplier record, including billing/shipping contacts and `default_markup`. A foreign, unknown or soft-deleted id is 404.\n\n**Requires scope:** `catalog:read`",
        "operationId": "suppliers.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SupplierDetail"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a supplier"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "Get a supplier",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "patch": {
        "description": "Accepts every field the admin update form accepts. A foreign or unknown id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "suppliers.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "billing_address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_fax": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_first_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing_state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "billing_zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "default_markup": {
                    "anyOf": [
                      {
                        "minimum": 0,
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "description": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  },
                  "shipping_address_1": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_address_2": {
                    "anyOf": [
                      {
                        "maxLength": 255,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_city": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_email": {
                    "anyOf": [
                      {
                        "format": "email",
                        "maxLength": 254,
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_fax": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_first_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_last_name": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "shipping_state": {
                    "anyOf": [
                      {
                        "maxLength": 100,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "shipping_zipcode": {
                    "anyOf": [
                      {
                        "maxLength": 20,
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SupplierDetail"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a supplier"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Update a supplier",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/tags": {
      "get": {
        "description": "Cursor-paginated: pass the previous response's `next_cursor` back as `cursor` to fetch the next page. Soft-deleted tags are omitted unless `include_deleted=true`, which only pairs with the default ascending `order`.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "tags.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Tag"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List tags"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "List tags",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "post": {
        "description": "The name is title-cased. Duplicate names (by slug) are refused with `409 CONFLICT`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "tags.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tag"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Create a tag"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Create a tag",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/tags/{id}": {
      "delete": {
        "description": "Soft-deletes the tag and removes its link from every product that carried it, in one transaction, matching the behaviour of the admin app.\n\n- Removing the link is a change to each affected product, so its `version` bumps and it reappears in the caller's next delta-sync poll.\n\n- `404 NOT_FOUND`: the id is foreign, unknown, or already deleted.\n\n**Requires scope:** `catalog:write`",
        "operationId": "tags.delete",
        "responses": {
          "204": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "description": "No content.",
                  "properties": {},
                  "type": "object"
                }
              }
            },
            "description": "Delete a tag"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Delete a tag",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      },
      "get": {
        "description": "The shape is identical to one element of `tags.list`. A foreign, unknown or soft-deleted id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:read`",
        "operationId": "tags.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tag"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Get a tag"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:read"
            ]
          }
        ],
        "summary": "Get a tag",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:read"
      },
      "patch": {
        "description": "A rename is title-cased and recomputes the uniqueness slug. Renaming onto another live tag is refused with `409 CONFLICT`. A foreign or unknown id is `404 NOT_FOUND`.\n\n**Requires scope:** `catalog:write`",
        "operationId": "tags.update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "maxLength": 85,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tag"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Update a tag"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": [
              "catalog:write"
            ]
          }
        ],
        "summary": "Update a tag",
        "tags": [
          "Catalog"
        ],
        "x-olet-scope": "catalog:write"
      }
    },
    "/taxes": {
      "get": {
        "description": "Readable by any valid credential: it is reference data needed to interpret product prices and sale totals, which are scoped to other permissions.\n\n- `400 VALIDATION_FAILED`: `include_deleted=true` combined with `order=desc`.\n\n**Requires scope:** `any`",
        "operationId": "taxes.list",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "Opaque. Pass back the exact next_cursor value from a previous response; never construct one. A cursor that fails to decode is 400 VALIDATION_FAILED, in every order mode.",
              "minLength": 1,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "schema": {
              "default": "asc",
              "enum": [
                "asc",
                "desc"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/Tax"
                      },
                      "type": "array"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "description": "Opaque pagination cursor. Pass back as ?cursor= to fetch the next page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "next_cursor",
                    "has_more"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "List taxes"
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "description": "An error response."
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List taxes",
        "tags": [
          "Store settings"
        ],
        "x-olet-scope": "any"
      }
    }
  },
  "security": [
    {
      "apiKey": []
    },
    {
      "oauth2": []
    }
  ],
  "servers": [
    {
      "url": "https://api.oletapp.com/{domain_prefix}/v1",
      "variables": {
        "domain_prefix": {
          "default": "your-store"
        }
      }
    }
  ],
  "tags": [
    {
      "description": "Your store identity, connection info and settings.",
      "name": "Account"
    },
    {
      "description": "Create, update and search the product catalog.",
      "name": "Products"
    },
    {
      "description": "Manage brands, categories, suppliers and tags used to organize products.",
      "name": "Catalog"
    },
    {
      "description": "Read and adjust stock levels across outlets.",
      "name": "Inventory"
    },
    {
      "description": "Manage customer records and their contact details.",
      "name": "Customers"
    },
    {
      "description": "Record and retrieve sales transactions.",
      "name": "Sales"
    },
    {
      "description": "Configure outlets, payment types and tax rates.",
      "name": "Store settings"
    }
  ]
}
