{
  "openapi": "3.1.0",
  "info": {
    "title": "Linkable Order API",
    "version": "1.0.0",
    "description": "Push orders to Shopify through the Linkable Order Queue. Authenticate with the Bearer token issued to your account."
  },
  "servers": [
    {
      "url": "https://api.eod-infinitee.com"
    }
  ],
  "security": [],
  "components": {
    "securitySchemes": {
      "ClientToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer token issued by Linkable. Pass in the `Authorization: Bearer <token>` header."
      }
    },
    "schemas": {
      "Store": {
        "type": "object",
        "properties": {
          "store_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "My Store"
          },
          "shop_domain": {
            "type": "string",
            "example": "my-store.myshopify.com"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "INACTIVE",
              "CREDENTIAL_ERROR"
            ]
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "example": "Classic T-Shirt"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "ARCHIVED",
              "DRAFT"
            ]
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "variant_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Use this as `variant_id` when creating an order."
                },
                "title": {
                  "type": "string",
                  "example": "Black / L"
                },
                "sku": {
                  "type": "string",
                  "example": "TS-BLK-L"
                },
                "price": {
                  "type": "string",
                  "example": "199000"
                }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "NOT_FOUND"
          },
          "message": {
            "type": "string",
            "example": "Resource not found"
          },
          "details": {
            "type": "object"
          }
        },
        "required": [
          "error",
          "message"
        ]
      },
      "Order": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "SUCCESS",
              "FAILED"
            ]
          },
          "idempotency_key": {
            "type": "string",
            "format": "uuid"
          },
          "shopify_order_id": {
            "type": "string",
            "nullable": true
          },
          "shopify_order_number": {
            "type": "string",
            "nullable": true
          },
          "duplicate": {
            "type": "boolean"
          },
          "queued_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PodOrder": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "reference_id": {
            "type": "string",
            "example": "REF-001"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "SUCCESS",
              "SYNCED",
              "FULFILLED",
              "FAILED",
              "CANCELLED"
            ]
          },
          "duplicate": {
            "type": "boolean"
          },
          "queue_position": {
            "type": "integer",
            "nullable": true
          },
          "addon_service": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "carton_box",
                "scan_label"
              ]
            },
            "description": "Dịch vụ bổ sung cấp đơn, dạng mảng (có thể có đồng thời carton_box và scan_label); mảng rỗng = không có add-on. Trước SOQ-546 trường này là chuỗi đơn hoặc null — client cũ cần đọc dạng mảng."
          },
          "pricing": {
            "type": "object",
            "properties": {
              "subtotal": {
                "type": "number",
                "example": 40.97
              },
              "shipping_total": {
                "type": "number",
                "example": 8.39
              },
              "discount_amount": {
                "type": "number",
                "example": 2.05
              },
              "grand_total": {
                "type": "number",
                "example": 47.31
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_via": {
            "type": "string",
            "enum": [
              "api",
              "portal_form",
              "portal_import",
              "ops_import"
            ],
            "description": "Nguồn tạo đơn: api (token tích hợp), portal_form (form trên Portal), portal_import (import file trên Portal), ops_import (import nội bộ). Chỉ có ở GET /v1/orders/pod và /v1/orders/pod/{order_id}."
          }
        }
      },
      "PodOrderLineItem": {
        "type": "object",
        "properties": {
          "line_item_id": {
            "type": "string",
            "format": "uuid"
          },
          "quantity": {
            "type": "integer"
          },
          "sides": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "line_total": {
            "type": "number",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "image_url": {
            "type": "string",
            "nullable": true,
            "description": "Ảnh sản phẩm của line item: ảnh riêng của variant, fallback về ảnh product, null nếu cả hai đều không có."
          },
          "addon_service": {
            "type": "string",
            "nullable": true,
            "description": "Dịch vụ bổ sung cấp line (fabric_applique, lace_applique_emb)."
          },
          "line_addon_surcharge": {
            "type": "number",
            "nullable": true,
            "description": "Phụ phí add-on cấp line (tính = đơn giá × quantity)."
          }
        }
      },
      "PodOrderDetail": {
        "type": "object",
        "description": "Chi tiết đơn POD bao gồm line items.",
        "allOf": [
          {
            "$ref": "#/components/schemas/PodOrder"
          },
          {
            "type": "object",
            "properties": {
              "customer": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "first_name": {
                    "type": "string"
                  },
                  "last_name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "shipping_address": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "address1": {
                    "type": "string"
                  },
                  "address2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "country_code": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string"
                  }
                }
              },
              "line_items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PodOrderLineItem"
                }
              }
            }
          }
        ]
      },
      "Webhook": {
        "type": "object",
        "description": "A registered webhook endpoint. Never includes the signing secret.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://example.com/hooks/linkable",
            "description": "HTTPS endpoint we POST events to."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Production order sync"
          },
          "topics": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order.created",
                "order.status_updated",
                "order.cancelled",
                "tracking.created",
                "tracking.updated"
              ]
            },
            "example": [
              "order.created",
              "order.status_updated"
            ],
            "description": "Topics this endpoint is subscribed to."
          },
          "is_active": {
            "type": "boolean",
            "description": "False when disabled — either by you or auto-disabled after 10 consecutive delivery failures."
          },
          "consecutive_failures": {
            "type": "integer",
            "example": 0,
            "description": "Deliveries that have failed in a row; reset to 0 on any success."
          },
          "disabled_reason": {
            "type": "string",
            "nullable": true,
            "example": "too_many_failures",
            "description": "Why the endpoint was disabled, when `is_active` is false."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "description",
          "topics",
          "is_active",
          "consecutive_failures",
          "disabled_reason",
          "created_at",
          "updated_at"
        ]
      },
      "WebhookWithSecret": {
        "type": "object",
        "description": "A webhook plus its plaintext signing `secret`. Returned ONCE — on create and on rotate-secret. Store it now; it is never shown again.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "example": "whsec_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
                "description": "HMAC-SHA256 signing secret. Use it to verify the `X-Webhook-Signature` header."
              }
            },
            "required": [
              "secret"
            ]
          }
        ]
      },
      "WebhookTopic": {
        "type": "object",
        "description": "A subscribable topic and its description.",
        "properties": {
          "topic": {
            "type": "string",
            "enum": [
              "order.created",
              "order.status_updated",
              "order.cancelled",
              "tracking.created",
              "tracking.updated"
            ],
            "example": "order.created"
          },
          "description": {
            "type": "string",
            "example": "An order was created."
          }
        },
        "required": [
          "topic",
          "description"
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "description": "A single delivery attempt log for one event to one webhook.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_id": {
            "type": "string",
            "format": "uuid",
            "description": "The event id — matches `X-Webhook-Id` and the envelope `id`."
          },
          "topic": {
            "type": "string",
            "example": "order.created",
            "description": "The event topic (or `webhook.test` for a manual test ping)."
          },
          "payload": {
            "allOf": [
              {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              }
            ],
            "description": "The exact envelope that was (or will be) POSTed."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "success",
              "failed"
            ]
          },
          "attempts": {
            "type": "integer",
            "example": 1,
            "description": "Number of delivery attempts made so far."
          },
          "last_status_code": {
            "type": "integer",
            "nullable": true,
            "example": 200,
            "description": "HTTP status of the most recent attempt, or null if none completed."
          },
          "last_error": {
            "type": "string",
            "nullable": true,
            "example": null,
            "description": "Error detail from the most recent failed attempt."
          },
          "next_retry_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the next retry is scheduled, or null when not pending a retry."
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the delivery first succeeded, or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "webhook_id",
          "event_id",
          "topic",
          "payload",
          "status",
          "attempts",
          "last_status_code",
          "last_error",
          "next_retry_at",
          "delivered_at",
          "created_at"
        ]
      },
      "WebhookEventEnvelope": {
        "type": "object",
        "description": "The JSON body we POST to your endpoint. `data` shape depends on `topic` — order/tracking topics carry an OrderEventData.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Event id — identical across every webhook that receives this event; use it to dedupe retries."
          },
          "topic": {
            "type": "string",
            "example": "order.created"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 timestamp of when the event was emitted."
          },
          "data": {
            "description": "Event payload. An OrderEventData for order/tracking topics.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/OrderEventData"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ]
          }
        },
        "required": [
          "id",
          "topic",
          "created_at",
          "data"
        ]
      },
      "OrderEventData": {
        "type": "object",
        "description": "Client-facing snapshot of an order carried by every order/tracking event.",
        "properties": {
          "order": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "reference_id": {
                "type": "string",
                "example": "REF-10023"
              },
              "store_id": {
                "type": "string",
                "format": "uuid"
              },
              "client_status": {
                "type": "string",
                "nullable": true,
                "example": "shipping",
                "description": "Client-facing status key, or null when none is set yet."
              },
              "shipment_status": {
                "type": "string",
                "nullable": true,
                "example": "in_transit",
                "description": "Shipment status derived from carrier tracking, or null when not shipping yet."
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "reference_id",
              "store_id",
              "client_status",
              "shipment_status",
              "created_at",
              "updated_at"
            ]
          },
          "tracking": {
            "type": "object",
            "nullable": true,
            "description": "Tracking snapshot; null when the order has no tracking number yet.",
            "properties": {
              "tracking_number": {
                "type": "string",
                "nullable": true,
                "example": "1Z999AA10123456784"
              },
              "carrier": {
                "type": "string",
                "nullable": true,
                "example": "UPS"
              },
              "tracking_url": {
                "type": "string",
                "format": "uri",
                "nullable": true,
                "example": "https://www.ups.com/track?tracknum=1Z999AA10123456784"
              },
              "shipment_status": {
                "type": "string",
                "nullable": true,
                "example": "in_transit"
              }
            },
            "required": [
              "tracking_number",
              "carrier",
              "tracking_url",
              "shipment_status"
            ]
          },
          "previous": {
            "type": "object",
            "additionalProperties": true,
            "description": "Only present on `*_updated` topics — the subset of fields that changed."
          }
        },
        "required": [
          "order",
          "tracking"
        ]
      },
      "FeatureFlag": {
        "type": "object",
        "description": "Global feature flag state.",
        "properties": {
          "key": {
            "type": "string",
            "example": "orders.create"
          },
          "label": {
            "type": "string",
            "example": "Create Orders"
          },
          "description": {
            "type": "string",
            "example": "Allow clients to create new orders via the API"
          },
          "registry_default": {
            "type": "boolean",
            "description": "Hardcoded default in the registry"
          },
          "default_enabled": {
            "type": "boolean",
            "description": "Current effective default (global override > registry)"
          },
          "source": {
            "type": "string",
            "enum": [
              "registry",
              "global"
            ],
            "description": "Where the current default comes from"
          },
          "updated_by": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "ClientFeature": {
        "type": "object",
        "description": "Feature state resolved for a specific client.",
        "properties": {
          "key": {
            "type": "string",
            "example": "orders.create"
          },
          "label": {
            "type": "string",
            "example": "Create Orders"
          },
          "description": {
            "type": "string",
            "example": "Allow clients to create new orders via the API"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether this feature is enabled for the client"
          },
          "source": {
            "type": "string",
            "enum": [
              "client",
              "global",
              "default"
            ],
            "description": "Resolution level: client override > global override > registry default"
          },
          "default_enabled": {
            "type": "boolean",
            "description": "Registry default value"
          }
        }
      },
      "ClientFeaturesResponse": {
        "type": "object",
        "description": "Simple feature map for client portal (no source/note leaked).",
        "properties": {
          "features": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "Map of feature key to enabled state",
            "example": {
              "orders.create": true,
              "orders.import": true,
              "orders.cancel": true,
              "orders.retry": true,
              "catalog.products": true,
              "wallet.view": true,
              "wallet.topup": true,
              "tickets": true,
              "webhooks": true,
              "api_tokens": true
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Stores",
      "description": "Browse available stores."
    },
    {
      "name": "Products",
      "description": "Browse products and get variant IDs for order creation."
    },
    {
      "name": "Orders",
      "description": "Create orders and track their delivery status."
    },
    {
      "name": "pod-integration",
      "description": "Print-on-Demand order API — tạo đơn POD, xem trạng thái, retry/cancel."
    },
    {
      "name": "config",
      "description": "Reference config — pricing sides, shipping rates, yarn types, country codes, special surcharges, carton box capacity."
    },
    {
      "name": "Webhooks",
      "description": "Register endpoints to receive signed event notifications (orders, tracking) instead of polling. Manage endpoints and inspect deliveries here; see the guide at /api-reference/webhooks for signature verification and the event payloads."
    },
    {
      "name": "Client Portal",
      "description": "Client portal endpoints for self-service operations."
    }
  ],
  "paths": {
    "/v1/stores": {
      "get": {
        "operationId": "listStores",
        "tags": [
          "Stores"
        ],
        "summary": "List stores",
        "description": "Returns all active stores available to your account. Use the `store_id` to browse products.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of stores.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Store"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/stores/{store_id}/products": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "Products"
        ],
        "summary": "List products",
        "description": "Returns products and their variants for a store. Use `variant_id` from a variant when creating an order.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Search query. Interpreted according to `search_type`: product title (default), product_id (UUID), shopify_id, or variant SKU. Example: `?q=HOODIE&search_type=sku` finds products with a variant SKU containing \"HOODIE\" (e.g. \"emb - HOODIE - MAROON-L\"). SKU search needs at least 3 characters."
          },
          {
            "name": "search_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "product_id",
                "shopify_id",
                "sku"
              ],
              "default": "name"
            },
            "description": "How to interpret `q`: `name` (ILIKE on title), `product_id` (exact UUID), `shopify_id` (exact Shopify product ID), `sku` (partial, case-insensitive match on variant SKU; `q` must be at least 3 characters, otherwise 400)."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "ARCHIVED",
                "DRAFT"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of products with variants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/stores/{store_id}/products/{product_id}": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "Products"
        ],
        "summary": "Get product detail",
        "description": "Returns a single product with all its variants. Use `variant_id` from a variant when creating an order.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product detail with variants.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "Product not found."
          }
        }
      }
    },
    "/v1/orders": {
      "post": {
        "operationId": "createOrder",
        "tags": [
          "Orders"
        ],
        "summary": "Create an order",
        "description": "Push a new order into the queue. The order will be delivered to Shopify automatically with rate-limit protection.\n\nUse `idempotency_key` to safely retry without creating duplicates.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "idempotency_key",
                  "customer",
                  "shipping_address",
                  "line_items"
                ],
                "properties": {
                  "idempotency_key": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Unique key per order — reuse the same key to safely retry without creating a duplicate."
                  },
                  "customer": {
                    "type": "object",
                    "required": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email",
                        "example": "nguyen@example.com"
                      },
                      "first_name": {
                        "type": "string",
                        "example": "Van"
                      },
                      "last_name": {
                        "type": "string",
                        "example": "Nguyen"
                      },
                      "phone": {
                        "type": "string",
                        "example": "+84901234567"
                      }
                    }
                  },
                  "shipping_address": {
                    "type": "object",
                    "required": [
                      "address1",
                      "city",
                      "province",
                      "country_code",
                      "zip"
                    ],
                    "properties": {
                      "address1": {
                        "type": "string",
                        "example": "123 Le Loi"
                      },
                      "address2": {
                        "type": "string",
                        "example": "Apt 4B"
                      },
                      "city": {
                        "type": "string",
                        "example": "Ho Chi Minh City"
                      },
                      "province": {
                        "type": "string",
                        "example": "Ho Chi Minh"
                      },
                      "country_code": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 2,
                        "example": "VN"
                      },
                      "zip": {
                        "type": "string",
                        "example": "700000"
                      }
                    }
                  },
                  "line_items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 250,
                    "items": {
                      "type": "object",
                      "required": [
                        "variant_id",
                        "quantity"
                      ],
                      "properties": {
                        "variant_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Variant UUID provided by Linkable."
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "example": 2
                        }
                      }
                    }
                  },
                  "note": {
                    "type": "string",
                    "description": "Optional order note."
                  },
                  "tags": {
                    "type": "string",
                    "description": "Comma-separated Shopify order tags."
                  },
                  "force": {
                    "type": "boolean",
                    "default": false,
                    "description": "Set `true` to bypass soft duplicate detection based on content hash."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order accepted and queued for delivery to Shopify.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token."
          },
          "409": {
            "description": "Duplicate: `DUPLICATE_REFERENCE_ID` (reference_id đã tồn tại) hoặc `POTENTIAL_DUPLICATE` (nội dung giống — pass `force: true` để bỏ qua)."
          },
          "422": {
            "description": "Validation error — check request body fields."
          }
        }
      },
      "get": {
        "operationId": "listOrders",
        "tags": [
          "Orders"
        ],
        "summary": "List orders",
        "description": "Retrieve a paginated list of your orders. Results are scoped to your client token.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "PROCESSING",
                "SUCCESS",
                "FAILED"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/orders/{order_id}": {
      "get": {
        "operationId": "getOrder",
        "tags": [
          "Orders"
        ],
        "summary": "Get order status",
        "description": "Retrieve the current status and details of a specific order including line items and delivery attempts.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order detail with line items and delivery attempts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "404": {
            "description": "Order not found."
          }
        }
      }
    },
    "/v1/orders/pod": {
      "post": {
        "operationId": "createPodOrder",
        "tags": [
          "pod-integration"
        ],
        "summary": "Create POD order",
        "description": "Tạo đơn hàng Print-on-Demand. Hệ thống tự validate, tính pricing, và push sang Shopify.\n\n`reference_id` là mã đơn **duy nhất trong mỗi store** — gửi trùng ref sẽ bị từ chối với lỗi `409 DUPLICATE_REFERENCE_ID` (không tạo mới, không trả order cũ).",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "customer",
                  "line_items"
                ],
                "properties": {
                  "reference_id": {
                    "type": "string",
                    "description": "Mã đơn hàng của bạn (tuỳ chọn, tối đa 100 ký tự). Bỏ trống thì đơn không có ref và không bị so trùng. Có ref thì duy nhất trong store — gửi trùng sẽ bị từ chối (409 DUPLICATE_REFERENCE_ID).",
                    "example": "ORD-20250624-001"
                  },
                  "shipping_service": {
                    "type": "string",
                    "enum": [
                      "eco",
                      "premium"
                    ],
                    "default": "eco"
                  },
                  "label_link": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL label tự cung cấp (TikTok, Etsy, ...). Có field này thì bỏ shipping_address. Phải đi kèm tracking_number."
                  },
                  "tracking_number": {
                    "type": "string",
                    "description": "Tracking number đi kèm label_link."
                  },
                  "customer": {
                    "type": "object",
                    "required": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email",
                        "example": "john@gmail.com"
                      },
                      "first_name": {
                        "type": "string",
                        "example": "John"
                      },
                      "last_name": {
                        "type": "string",
                        "example": "Doe"
                      },
                      "phone": {
                        "type": "string",
                        "example": "+14155551234"
                      }
                    }
                  },
                  "shipping_address": {
                    "type": "object",
                    "description": "Địa chỉ nhận hàng. Không cần khi đã cung cấp label_link.",
                    "required": [
                      "address1",
                      "city",
                      "province",
                      "country_code",
                      "zip"
                    ],
                    "properties": {
                      "address1": {
                        "type": "string",
                        "example": "123 Main St"
                      },
                      "address2": {
                        "type": "string",
                        "example": "Apt 4B"
                      },
                      "city": {
                        "type": "string",
                        "example": "Los Angeles"
                      },
                      "province": {
                        "type": "string",
                        "example": "CA"
                      },
                      "country_code": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 2,
                        "example": "US"
                      },
                      "zip": {
                        "type": "string",
                        "example": "90001"
                      }
                    }
                  },
                  "line_items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 250,
                    "items": {
                      "type": "object",
                      "required": [
                        "variant_id",
                        "quantity",
                        "sides"
                      ],
                      "properties": {
                        "variant_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "UUID sản phẩm (lấy từ Products API)."
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "example": 2
                        },
                        "sides": {
                          "type": "object",
                          "description": "Design URL cho mỗi mặt in. Keys: front_side, front_large, back, pocket_chest_left, pocket_chest_right, left_sleeve, right_sleeve, special_location.",
                          "additionalProperties": {
                            "type": "string",
                            "format": "uri"
                          },
                          "example": {
                            "front_side": "https://cdn.example.com/design-front.png",
                            "back": "https://cdn.example.com/design-back.png"
                          }
                        },
                        "printing_technique": {
                          "type": "string",
                          "enum": [
                            "DTG",
                            "DTF"
                          ],
                          "description": "Bắt buộc cho printing."
                        },
                        "no_printing_file": {
                          "type": "boolean",
                          "description": "Khách không có file in: +$2/sản phẩm. Không áp dụng cho nón (cap-like) và tote."
                        },
                        "emb_file": {
                          "type": "string",
                          "enum": [
                            "Available",
                            "No EMB file"
                          ],
                          "description": "Bắt buộc cho embroidery."
                        },
                        "design_emb_type": {
                          "type": "string",
                          "enum": [
                            "text only",
                            "vector / cartoon artwork",
                            "Photo to Embroidery"
                          ]
                        },
                        "number_of_pets": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 4,
                          "description": "Bắt buộc khi Photo to Embroidery."
                        },
                        "yarn_type": {
                          "type": "string",
                          "enum": [
                            "yarn_6_7mm",
                            "yarn_8_10mm",
                            "yarn_20mm",
                            "plat_emb",
                            "emb_3d_puff"
                          ]
                        },
                        "addon_service": {
                          "type": "string",
                          "enum": [
                            "fabric_applique",
                            "lace_applique_emb"
                          ],
                          "description": "Dịch vụ bổ sung cấp line-item, tính theo quantity: fabric_applique ($1.50/item) hoặc lace_applique_emb ($2.00/item)."
                        },
                        "note": {
                          "type": "string",
                          "description": "Ghi chú cho sản phẩm."
                        }
                      }
                    }
                  },
                  "addon_service": {
                    "oneOf": [
                      {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "carton_box",
                            "scan_label"
                          ]
                        },
                        "example": [
                          "carton_box",
                          "scan_label"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "carton_box",
                          "scan_label"
                        ]
                      }
                    ],
                    "description": "Dịch vụ bổ sung cấp đơn hàng, nhận mảng ([\"carton_box\",\"scan_label\"]) hoặc chuỗi đơn (tương thích ngược, được chuẩn hoá về mảng); giá trị trùng bị bỏ, mảng rỗng = không add-on. carton_box (tính phí theo box, items/box phụ thuộc category và store), scan_label ($1/đơn flat). Phí addon_surcharge là tổng các add-on đã chọn."
                  },
                  "note": {
                    "type": "string",
                    "description": "Ghi chú đơn hàng."
                  },
                  "tags": {
                    "type": "string",
                    "description": "Tags (comma-separated)."
                  },
                  "force": {
                    "type": "boolean",
                    "default": false,
                    "description": "Set `true` để bỏ qua kiểm tra trùng nội dung."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Order accepted and queued for delivery to Shopify.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodOrder"
                }
              }
            }
          },
          "400": {
            "description": "Validation error — kiểm tra request body."
          },
          "401": {
            "description": "Missing or invalid Bearer token."
          },
          "409": {
            "description": "Trùng đơn:\n- `DUPLICATE_REFERENCE_ID` — `reference_id` đã tồn tại trong store (đổi ref khác để tạo đơn mới).\n- `POTENTIAL_DUPLICATE` — nội dung giống một đơn trong dedup window; gửi lại với `force: true` để bỏ qua.\n\nBody có `error` (code) và `details.existing_order`."
          }
        }
      },
      "get": {
        "operationId": "listPodOrders",
        "tags": [
          "pod-integration"
        ],
        "summary": "List POD orders",
        "description": "Danh sách đơn POD của bạn, hỗ trợ cursor pagination và filter theo status.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "PROCESSING",
                "SUCCESS",
                "SYNCED",
                "FULFILLED",
                "FAILED",
                "CANCELLED"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of POD orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PodOrder"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/orders/pod/{order_id}": {
      "get": {
        "operationId": "getPodOrder",
        "tags": [
          "pod-integration"
        ],
        "summary": "Get POD order",
        "description": "Chi tiết đơn POD bao gồm line items, pricing breakdown, và delivery attempts.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "POD order detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodOrderDetail"
                }
              }
            }
          },
          "404": {
            "description": "Order not found."
          }
        }
      }
    },
    "/v1/orders/pod/{order_id}/retry": {
      "post": {
        "operationId": "retryPodOrder",
        "tags": [
          "pod-integration"
        ],
        "summary": "Retry failed POD order",
        "description": "Retry đơn FAILED — đưa lại vào queue để push sang Shopify. Tối đa 5 lần retry.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order queued for retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodOrder"
                }
              }
            }
          },
          "400": {
            "description": "Order is not in FAILED status or max retries exceeded."
          },
          "404": {
            "description": "Order not found."
          }
        }
      }
    },
    "/v1/orders/pod/{order_id}/cancel": {
      "post": {
        "operationId": "cancelPodOrder",
        "tags": [
          "pod-integration"
        ],
        "summary": "Cancel POD order",
        "description": "Hủy đơn đang ở trạng thái PENDING hoặc FAILED.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order cancelled. `warnings` is present only when the cancel left something outstanding — most often a shipping label the carrier refused to void, which stays live and billable.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "CANCELLED"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Human-readable notes about what the cancel could not finish."
                    }
                  },
                  "required": [
                    "order_id",
                    "status"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Order cannot be cancelled (not PENDING or FAILED)."
          },
          "404": {
            "description": "Order not found."
          }
        }
      }
    },
    "/v1/orders/pod/{order_id}/shipping": {
      "get": {
        "operationId": "getPodOrderShipping",
        "tags": [
          "pod-integration"
        ],
        "summary": "Get shipping label for a POD order",
        "description": "Nhãn vận chuyển đã mua cho đơn. Trả `null` khi chưa có nhãn còn hiệu lực — đơn chưa mua, mua hỏng, hoặc nhãn đã bị huỷ.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Shipping label, or null when the order has none.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "carrier": {
                      "type": "string",
                      "nullable": true
                    },
                    "tracking_number": {
                      "type": "string",
                      "nullable": true
                    },
                    "label_url": {
                      "type": "string",
                      "description": "Link tới storage của carrier. Ưu tiên dùng `/shipping/file` thay cho link này — link carrier có thể hết hạn hoặc sập, còn nhãn thì không cấp lại được, chỉ mua lại được."
                    },
                    "label_format": {
                      "type": "string",
                      "nullable": true,
                      "example": "PDF"
                    },
                    "label_purchased_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "fulfilled_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "is_voided": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Order not found."
          }
        }
      }
    },
    "/v1/orders/pod/{order_id}/shipping/file": {
      "get": {
        "operationId": "getPodOrderShippingFile",
        "tags": [
          "pod-integration"
        ],
        "summary": "Download the shipping label file",
        "description": "Chính file nhãn. Trả bản sao trong storage của hệ thống khi có, và chỉ lấy từ carrier khi chưa có bản sao — nên endpoint này vẫn chạy sau khi link carrier hết hạn. Header `X-Label-Source` cho biết bản nào đã trả lời: `archive` hoặc `provider`.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The label file.",
            "headers": {
              "X-Label-Source": {
                "description": "Which copy served the request.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "archive",
                    "provider"
                  ]
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Order not found, or it has no live shipping label."
          }
        }
      }
    },
    "/v1/config/pricing-sides": {
      "get": {
        "operationId": "getPricingSides",
        "tags": [
          "config"
        ],
        "summary": "Get pricing sides config",
        "description": "Bảng phụ phí mặt in theo category. Dùng để tính trước giá đơn hàng.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Pricing sides configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "category": {
                            "type": "string"
                          },
                          "side_code": {
                            "type": "string"
                          },
                          "surcharge": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/shipping-rates": {
      "get": {
        "operationId": "getShippingRates",
        "tags": [
          "config"
        ],
        "summary": "Get shipping rates",
        "description": "Bảng phí ship theo category và service type (eco/premium).",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Shipping rates.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "category": {
                            "type": "string"
                          },
                          "service_type": {
                            "type": "string"
                          },
                          "base_rate": {
                            "type": "number"
                          },
                          "additional_rate": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/yarn-types": {
      "get": {
        "operationId": "getYarnTypes",
        "tags": [
          "config"
        ],
        "summary": "Get yarn types",
        "description": "Loại chỉ thêu và phí bổ sung.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Yarn types configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "category": {
                            "type": "string"
                          },
                          "type_code": {
                            "type": "string"
                          },
                          "extra_cost": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/country-codes": {
      "get": {
        "operationId": "getCountryCodes",
        "tags": [
          "config"
        ],
        "summary": "Get valid country codes",
        "description": "Danh sách quốc gia hợp lệ cho shipping_address.country_code.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Country codes list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "example": "US"
                          },
                          "name": {
                            "type": "string",
                            "example": "United States"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/special-surcharges": {
      "get": {
        "operationId": "getSpecialSurcharges",
        "tags": [
          "config"
        ],
        "summary": "Get special surcharges",
        "description": "Bảng phụ phí đặc biệt (DTG, EMB, addon services).",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Special surcharges.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "surcharge_type": {
                            "type": "string"
                          },
                          "condition_key": {
                            "type": "string"
                          },
                          "amount": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/carton-box-config": {
      "get": {
        "operationId": "getCartonBoxConfig",
        "tags": [
          "config"
        ],
        "summary": "Get carton box capacity config",
        "description": "Cấu hình số items/box theo category và store. Dùng để tính phí carton box add-on: $4 (box đầu) + $1/box thêm. Số box = ceil(items / items_per_box) tính riêng cho mỗi category.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "store_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter theo store (optional). Nếu không truyền, trả tất cả stores."
          }
        ],
        "responses": {
          "200": {
            "description": "Carton box capacity config.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "store_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "store_name": {
                            "type": "string"
                          },
                          "category": {
                            "type": "string",
                            "example": "tshirt"
                          },
                          "items_per_box": {
                            "type": "integer",
                            "example": 5,
                            "description": "Số sản phẩm tối đa mỗi box cho category này."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/topics": {
      "get": {
        "operationId": "listWebhookTopics",
        "tags": [
          "Webhooks"
        ],
        "summary": "List available topics",
        "description": "List the event topics you can subscribe a webhook to, with a short description of each.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The subscribable topics.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookTopic"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List your webhooks",
        "description": "List every webhook endpoint registered for your account. Signing secrets are never returned here.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Your webhook endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Register a webhook",
        "description": "Register a new webhook endpoint. The response includes the plaintext signing `secret` **once** — store it now; it is never returned again. A client may register at most 5 webhooks.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "topics"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "example": "https://example.com/hooks/linkable",
                    "description": "HTTPS endpoint (must resolve to a public address)."
                  },
                  "topics": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.created",
                        "order.status_updated",
                        "order.cancelled",
                        "tracking.created",
                        "tracking.updated"
                      ]
                    },
                    "example": [
                      "order.created",
                      "order.status_updated"
                    ],
                    "description": "One or more topics to subscribe to. Must be unique."
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000,
                    "example": "Production order sync"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created. `secret` is present here only.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — one of `VALIDATION_ERROR` (invalid body/params), `INVALID_WEBHOOK_URL` (scheme/SSRF check failed), `WEBHOOK_LIMIT_REACHED` (max 5 webhooks per client), or `WEBHOOK_INACTIVE` (test send on a disabled endpoint).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/{id}": {
      "patch": {
        "operationId": "updateWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook",
        "description": "Update a webhook. Provide at least one field. Setting `is_active: true` re-activates an auto-disabled endpoint and clears its failure counter.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Webhook id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "topics": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.created",
                        "order.status_updated",
                        "order.cancelled",
                        "tracking.created",
                        "tracking.updated"
                      ]
                    }
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000,
                    "nullable": true
                  },
                  "is_active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — one of `VALIDATION_ERROR` (invalid body/params), `INVALID_WEBHOOK_URL` (scheme/SSRF check failed), `WEBHOOK_LIMIT_REACHED` (max 5 webhooks per client), or `WEBHOOK_INACTIVE` (test send on a disabled endpoint).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook",
        "description": "Permanently delete a webhook endpoint.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Webhook id."
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate signing secret",
        "description": "Issue a new signing secret for a webhook, invalidating the old one. The new plaintext `secret` is returned **once**.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Webhook id."
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook with its new `secret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Send a one-off `webhook.test` event to this endpoint (regardless of its subscribed topics) so you can confirm your endpoint receives and verifies our signature. The endpoint must be active.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Webhook id."
          }
        ],
        "responses": {
          "202": {
            "description": "Test delivery queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — one of `VALIDATION_ERROR` (invalid body/params), `INVALID_WEBHOOK_URL` (scheme/SSRF check failed), `WEBHOOK_LIMIT_REACHED` (max 5 webhooks per client), or `WEBHOOK_INACTIVE` (test send on a disabled endpoint).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "List recent deliveries",
        "description": "List recent delivery attempts for one webhook, most recent first.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Webhook id."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "1-based page number."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated delivery log.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request — one of `VALIDATION_ERROR` (invalid body/params), `INVALID_WEBHOOK_URL` (scheme/SSRF check failed), `WEBHOOK_LIMIT_REACHED` (max 5 webhooks per client), or `WEBHOOK_INACTIVE` (test send on a disabled endpoint).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/webhooks/deliveries/{delivery_id}/redeliver": {
      "post": {
        "operationId": "redeliverWebhookDelivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "Re-queue a delivery",
        "description": "Reset a delivery to a fresh attempt cycle and re-enqueue it.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Delivery id."
          }
        ],
        "responses": {
          "202": {
            "description": "Delivery re-queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid Bearer token (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Webhook or delivery not found (`NOT_FOUND`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/storage-plans": {
      "get": {
        "operationId": "listStoragePlans",
        "tags": [
          "Client Portal"
        ],
        "summary": "List storage plans",
        "description": "Active storage plans for comparison (no prices).",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Active plans, ordered by `sort_order`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true
                          },
                          "storage_limit_bytes": {
                            "type": "integer",
                            "nullable": true,
                            "description": "null = unlimited."
                          },
                          "max_file_size_bytes": {
                            "type": "integer"
                          },
                          "sort_order": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/design-files": {
      "get": {
        "operationId": "listDesignFiles",
        "tags": [
          "Client Portal"
        ],
        "summary": "List your design files",
        "description": "Design files stored by the authenticated client, newest first, with storage usage. Never includes other clients' files.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of design files plus `usage`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "Public file URL: `DESIGN_FILES_PUBLIC_URL/design-files/{client_id}/{file}` when the dedicated bucket is configured, otherwise `{API_BASE_URL}/v1/design-files/{client_id}/{file}`. When link signing is on it ends with `?exp={unixMs}&sig={hmac}`: the link expires after 90 days and an invalid or expired one answers 404. Call this list again to get a fresh link. Use the URL as-is; do not strip the query."
                          },
                          "path": {
                            "type": "string",
                            "description": "Path relative to the API base (`design-files/{client_id}/{file}`); use it for DELETE."
                          },
                          "file_name": {
                            "type": "string"
                          },
                          "size": {
                            "type": "integer"
                          },
                          "content_type": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "description": "Storage usage in bytes. `file_count` is for display only — files are limited by bytes, never by count.",
                      "properties": {
                        "used_bytes": {
                          "type": "integer",
                          "example": 52428800
                        },
                        "limit_bytes": {
                          "type": "integer",
                          "nullable": true,
                          "description": "null = unlimited.",
                          "example": 1073741824
                        },
                        "file_count": {
                          "type": "integer",
                          "example": 12
                        },
                        "plan": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "code": {
                              "type": "string",
                              "example": "free"
                            },
                            "name": {
                              "type": "string",
                              "example": "Free"
                            },
                            "storage_limit_bytes": {
                              "type": "integer",
                              "nullable": true
                            },
                            "max_file_size_bytes": {
                              "type": "integer",
                              "example": 20971520
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "uploadDesignFile",
        "tags": [
          "Client Portal"
        ],
        "summary": "Upload a design file",
        "description": "Multipart upload (`file`: pdf, png, jpg, jpeg, emb; max 20MB). Storage is limited by bytes according to the client's storage plan, never by number of files. If used + new file size exceeds the plan's storage the request fails with 403 `STORAGE_LIMIT_REACHED` (`details`: `{used_bytes, limit_bytes, plan}`); a file larger than the plan's per-file limit fails with 413 `FILE_TOO_LARGE`. Nothing is stored in either case.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored. Returns `data` (url, path, file_name, content_type, size) plus `usage`."
          },
          "400": {
            "description": "Missing file or invalid format."
          },
          "403": {
            "description": "Storage plan full — `STORAGE_LIMIT_REACHED`, details `{used_bytes, limit_bytes, plan}`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "File larger than the plan's per-file limit — `FILE_TOO_LARGE`."
          }
        }
      }
    },
    "/v1/design-files/{client_id}/{file}": {
      "delete": {
        "operationId": "deleteDesignFile",
        "tags": [
          "Client Portal"
        ],
        "summary": "Delete a design file",
        "description": "Removes the file and frees its bytes. Only the owning client can delete.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "404": {
            "description": "Not found."
          }
        }
      }
    },
    "/v1/me/features": {
      "get": {
        "operationId": "getMyFeatures",
        "tags": [
          "Client Portal"
        ],
        "summary": "Get my feature flags",
        "description": "Get the current client's enabled features. Returns a simple map of feature key to boolean — no source/note information is leaked.",
        "security": [
          {
            "ClientToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Feature flags for the current client.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientFeaturesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials (`UNAUTHORIZED`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "order.created": {
      "post": {
        "operationId": "onOrderCreated",
        "summary": "order.created",
        "description": "An order was created. We POST a signed `WebhookEventEnvelope` with `topic: \"order.created\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "order.created"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "order.created",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "order": {
                    "id": "33333333-3333-3333-3333-333333333333",
                    "reference_id": "REF-10023",
                    "store_id": "44444444-4444-4444-4444-444444444444",
                    "client_status": "shipping",
                    "shipment_status": "in_transit",
                    "created_at": "2026-01-01T00:00:00.000Z",
                    "updated_at": "2026-01-01T00:05:00.000Z"
                  },
                  "tracking": null
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    },
    "order.status_updated": {
      "post": {
        "operationId": "onOrderStatus_updated",
        "summary": "order.status_updated",
        "description": "An order's status changed. We POST a signed `WebhookEventEnvelope` with `topic: \"order.status_updated\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "order.status_updated"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "order.status_updated",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "order": {
                    "id": "33333333-3333-3333-3333-333333333333",
                    "reference_id": "REF-10023",
                    "store_id": "44444444-4444-4444-4444-444444444444",
                    "client_status": "shipping",
                    "shipment_status": "in_transit",
                    "created_at": "2026-01-01T00:00:00.000Z",
                    "updated_at": "2026-01-01T00:05:00.000Z"
                  },
                  "tracking": null
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    },
    "order.cancelled": {
      "post": {
        "operationId": "onOrderCancelled",
        "summary": "order.cancelled",
        "description": "An order was cancelled. We POST a signed `WebhookEventEnvelope` with `topic: \"order.cancelled\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "order.cancelled"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "order.cancelled",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "order": {
                    "id": "33333333-3333-3333-3333-333333333333",
                    "reference_id": "REF-10023",
                    "store_id": "44444444-4444-4444-4444-444444444444",
                    "client_status": "shipping",
                    "shipment_status": "in_transit",
                    "created_at": "2026-01-01T00:00:00.000Z",
                    "updated_at": "2026-01-01T00:05:00.000Z"
                  },
                  "tracking": null
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    },
    "tracking.created": {
      "post": {
        "operationId": "onTrackingCreated",
        "summary": "tracking.created",
        "description": "A tracking number was assigned to an order. We POST a signed `WebhookEventEnvelope` with `topic: \"tracking.created\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "tracking.created"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "tracking.created",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "order": {
                    "id": "33333333-3333-3333-3333-333333333333",
                    "reference_id": "REF-10023",
                    "store_id": "44444444-4444-4444-4444-444444444444",
                    "client_status": "shipping",
                    "shipment_status": "in_transit",
                    "created_at": "2026-01-01T00:00:00.000Z",
                    "updated_at": "2026-01-01T00:05:00.000Z"
                  },
                  "tracking": {
                    "tracking_number": "1Z999AA10123456784",
                    "carrier": "UPS",
                    "tracking_url": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
                    "shipment_status": "in_transit"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    },
    "tracking.updated": {
      "post": {
        "operationId": "onTrackingUpdated",
        "summary": "tracking.updated",
        "description": "A shipment tracking update was received. We POST a signed `WebhookEventEnvelope` with `topic: \"tracking.updated\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "tracking.updated"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "tracking.updated",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "order": {
                    "id": "33333333-3333-3333-3333-333333333333",
                    "reference_id": "REF-10023",
                    "store_id": "44444444-4444-4444-4444-444444444444",
                    "client_status": "shipping",
                    "shipment_status": "in_transit",
                    "created_at": "2026-01-01T00:00:00.000Z",
                    "updated_at": "2026-01-01T00:05:00.000Z"
                  },
                  "tracking": {
                    "tracking_number": "1Z999AA10123456784",
                    "carrier": "UPS",
                    "tracking_url": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
                    "shipment_status": "in_transit"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    },
    "webhook.test": {
      "post": {
        "operationId": "onWebhookTest",
        "summary": "webhook.test",
        "description": "A manual test ping triggered via the test endpoint. We POST a signed `WebhookEventEnvelope` with `topic: \"webhook.test\"` to your registered endpoint.",
        "parameters": [
          {
            "name": "Content-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json"
              ]
            }
          },
          {
            "name": "User-Agent",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "ShopifyOrderQueue-Webhook/1.0"
            }
          },
          {
            "name": "X-Webhook-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The event id (matches the envelope `id`); stable across retries."
          },
          {
            "name": "X-Webhook-Topic",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "webhook.test"
            }
          },
          {
            "name": "X-Webhook-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1700000000"
            },
            "description": "Unix seconds; part of the signed string. Reject stale requests."
          },
          {
            "name": "X-Webhook-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "sha256=<hex>"
            },
            "description": "HMAC-SHA256 over `\"<X-Webhook-Timestamp>.<raw request body>\"` using your signing secret, hex-encoded and prefixed `sha256=`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventEnvelope"
              },
              "example": {
                "id": "11111111-1111-1111-1111-111111111111",
                "topic": "webhook.test",
                "created_at": "2026-01-01T00:00:00.000Z",
                "data": {
                  "message": "This is a test event from Shopify Order Queue.",
                  "webhook_id": "22222222-2222-2222-2222-222222222222"
                }
              }
            }
          }
        },
        "responses": {
          "2xx": {
            "description": "Any 2xx acknowledges receipt — the delivery is marked successful and not retried."
          },
          "default": {
            "description": "Any non-2xx response (or no response within 10s) is treated as a failure and retried on the backoff schedule 1m, 5m, 30m, 2h, 6h, 12h (7 attempts total). An endpoint that fails 10 deliveries in a row is auto-disabled."
          }
        }
      }
    }
  }
}