{
  "openapi": "3.0.3",
  "info": {
    "title": "Cart Service API",
    "description": "HTTP API for shopping cart operations (cookie-based or explicit id): retrieve cart, add/replace items, update quantity, manage deliveries.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://cart.tornberg.me",
      "description": "Production server"
    },
    {
      "url": "http://localhost:8080",
      "description": "Local development (cart API mounted under /cart)"
    }
  ],
  "paths": {
    "/cart": {
      "get": {
        "summary": "Get (or create) current cart (cookie based)",
        "description": "Returns the current cart. If no cartid cookie is present a new cart is created and Set-Cart-Id response header plus a Set-Cookie header are sent.",
        "responses": {
          "200": {
            "description": "Cart retrieved",
            "headers": {
              "Set-Cart-Id": {
                "description": "Returned when a new cart was created this request",
                "schema": { "type": "string" }
              },
              "X-Pod-Name": {
                "description": "Pod identifier serving the request",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "500": { "description": "Server error" }
        }
      },
      "post": {
        "summary": "Add single SKU (body)",
        "description": "Adds (or increases quantity of) a single SKU using request body.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AddRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Item added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid request body" },
          "500": { "description": "Server error" }
        }
      },
      "put": {
        "summary": "Change quantity of an item",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChangeQuantity" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quantity updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid request body" },
          "500": { "description": "Server error" }
        }
      },
      "delete": {
        "summary": "Clear cart cookie (logical cart reused only if referenced later)",
        "description": "Removes the cartid cookie by expiring it. Does not mutate server-side cart state.",
        "responses": {
          "200": { "description": "Cookie cleared (empty body)" }
        }
      }
    },
    "/cart/add/{sku}": {
      "get": {
        "summary": "Add a SKU (path)",
        "description": "Adds a single SKU with implicit quantity 1. Country inferred from Host header (-se / -no).",
        "parameters": [{ "$ref": "#/components/parameters/SkuParam" }],
        "responses": {
          "200": {
            "description": "Item added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/add": {
      "post": {
        "summary": "Add multiple items (append)",
        "description": "Adds multiple items to the cart without clearing existing contents.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SetCartItems" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Items added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/set": {
      "post": {
        "summary": "Replace cart contents",
        "description": "Clears the cart first, then adds the provided items (idempotent with respect to target set).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SetCartItems" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cart replaced",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/{itemId}": {
      "delete": {
        "summary": "Remove item by line id",
        "parameters": [
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": { "type": "integer", "format": "int64", "minimum": 0 },
            "description": "Internal cart line item identifier (not SKU)."
          }
        ],
        "responses": {
          "200": {
            "description": "Item removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Bad id" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/delivery": {
      "post": {
        "summary": "Set (add) delivery",
        "description": "Adds a delivery option referencing one or more line item ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SetDeliveryRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delivery added/updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/delivery/{deliveryId}": {
      "delete": {
        "summary": "Remove delivery",
        "parameters": [{ "$ref": "#/components/parameters/DeliveryIdParam" }],
        "responses": {
          "200": {
            "description": "Delivery removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Bad id" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/delivery/{deliveryId}/pickupPoint": {
      "put": {
        "summary": "Set pickup point for delivery",
        "parameters": [{ "$ref": "#/components/parameters/DeliveryIdParam" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PickupPoint" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pickup point set",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/voucher": {
      "put": {
        "summary": "Add voucher to cart",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AddVoucherRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Voucher added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/subscription-details": {
      "put": {
        "summary": "Upsert subscription details",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertSubscriptionDetails"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription details updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/voucher/{voucherId}": {
      "delete": {
        "summary": "Remove voucher from cart",
        "parameters": [{ "$ref": "#/components/parameters/VoucherIdParam" }],
        "responses": {
          "200": {
            "description": "Voucher removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid id" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}": {
      "get": {
        "summary": "Get cart by explicit id",
        "parameters": [{ "$ref": "#/components/parameters/CartIdParam" }],
        "responses": {
          "200": {
            "description": "Cart retrieved",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid id" },
          "500": { "description": "Server error" }
        }
      },
      "post": {
        "summary": "Add single SKU (body) by cart id",
        "parameters": [{ "$ref": "#/components/parameters/CartIdParam" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AddRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Item added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      },
      "put": {
        "summary": "Change quantity (by id variant)",
        "parameters": [{ "$ref": "#/components/parameters/CartIdParam" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChangeQuantity" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quantity updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/add/{sku}": {
      "get": {
        "summary": "Add SKU (path) by explicit cart id",
        "parameters": [
          { "$ref": "#/components/parameters/CartIdParam" },
          { "$ref": "#/components/parameters/SkuParam" }
        ],
        "responses": {
          "200": {
            "description": "Item added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid id/sku" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/{itemId}": {
      "delete": {
        "summary": "Remove item (by id variant)",
        "parameters": [
          { "$ref": "#/components/parameters/CartIdParam" },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": { "type": "integer", "format": "int64", "minimum": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "Item removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid id" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/delivery": {
      "post": {
        "summary": "Set delivery (by id variant)",
        "parameters": [{ "$ref": "#/components/parameters/CartIdParam" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SetDeliveryRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delivery added/updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/delivery/{deliveryId}": {
      "delete": {
        "summary": "Remove delivery (by id variant)",
        "parameters": [
          { "$ref": "#/components/parameters/CartIdParam" },
          { "$ref": "#/components/parameters/DeliveryIdParam" }
        ],
        "responses": {
          "200": {
            "description": "Delivery removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid ids" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/delivery/{deliveryId}/pickupPoint": {
      "put": {
        "summary": "Set pickup point (by id variant)",
        "parameters": [
          { "$ref": "#/components/parameters/CartIdParam" },
          { "$ref": "#/components/parameters/DeliveryIdParam" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PickupPoint" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pickup point updated",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/voucher": {
      "put": {
        "summary": "Add voucher (by id variant)",
        "parameters": [{ "$ref": "#/components/parameters/CartIdParam" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AddVoucherRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Voucher added",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid body" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/cart/byid/{id}/voucher/{voucherId}": {
      "delete": {
        "summary": "Remove voucher (by id variant)",
        "parameters": [
          { "$ref": "#/components/parameters/CartIdParam" },
          { "$ref": "#/components/parameters/VoucherIdParam" }
        ],
        "responses": {
          "200": {
            "description": "Voucher removed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CartGrain" }
              }
            }
          },
          "400": { "description": "Invalid ids" },
          "500": { "description": "Server error" }
        }
      }
    },
    "/healthz": {
      "get": {
        "summary": "Liveness & capacity probe",
        "responses": {
          "200": { "description": "Healthy" },
          "500": { "description": "Unhealthy" }
        }
      }
    },
    "/readyz": {
      "get": {
        "summary": "Readiness probe",
        "responses": {
          "200": { "description": "Ready" }
        }
      }
    },
    "/livez": {
      "get": {
        "summary": "Liveness probe",
        "responses": {
          "200": { "description": "Alive" }
        }
      }
    },
    "/version": {
      "get": {
        "summary": "Service version",
        "responses": {
          "200": {
            "description": "Version string",
            "content": {
              "text/plain": {
                "schema": { "type": "string", "example": "1.0.0" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "SkuParam": {
        "name": "sku",
        "in": "path",
        "required": true,
        "schema": { "type": "string" }
      },
      "CartIdParam": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Base62 encoded cart id",
        "schema": {
          "type": "string",
          "pattern": "^[0-9A-Za-z]+$",
          "minLength": 1
        }
      },
      "DeliveryIdParam": {
        "name": "deliveryId",
        "in": "path",
        "required": true,
        "schema": { "type": "integer", "format": "int64", "minimum": 0 }
      },
      "VoucherIdParam": {
        "name": "voucherId",
        "in": "path",
        "required": true,
        "schema": { "type": "integer", "format": "int64", "minimum": 0 }
      }
    },
    "schemas": {
      "CartGrain": {
        "type": "object",
        "description": "Cart aggregate (actor state)",
        "properties": {
          "id": {
            "type": "string",
            "description": "Cart id (base62 encoded uint64)"
          },
          "items": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CartItem" }
          },
          "totalPrice": { "type": "integer", "format": "int64" },
          "totalTax": { "type": "integer", "format": "int64" },
          "totalDiscount": { "type": "integer", "format": "int64" },
          "deliveries": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CartDelivery" }
          },
          "processing": { "type": "boolean" },
          "paymentInProgress": { "type": "boolean" },
          "orderReference": { "type": "string" },
          "paymentStatus": { "type": "string" },
          "vouchers": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Voucher" }
          },
          "subscriptionDetails": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/SubscriptionDetails"
            }
          }
        },
        "required": ["id", "items", "totalPrice", "totalTax", "totalDiscount"]
      },
      "CartItem": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "itemId": { "type": "integer" },
          "parentId": { "type": "integer" },
          "sku": { "type": "string" },
          "name": { "type": "string" },
          "price": { "type": "integer", "format": "int64" },
          "totalPrice": { "type": "integer", "format": "int64" },
          "totalTax": { "type": "integer", "format": "int64" },
          "orgPrice": { "type": "integer", "format": "int64" },
          "stock": {
            "type": "integer",
            "description": "0=OutOfStock,1=LowStock,2=InStock"
          },
          "qty": { "type": "integer" },
          "tax": { "type": "integer" },
          "taxRate": { "type": "integer" },
          "brand": { "type": "string" },
          "category": { "type": "string" },
          "category2": { "type": "string" },
          "category3": { "type": "string" },
          "category4": { "type": "string" },
          "category5": { "type": "string" },
          "disclaimer": { "type": "string" },
          "sellerId": { "type": "string" },
          "sellerName": { "type": "string" },
          "type": { "type": "string", "description": "Article type" },
          "image": { "type": "string" },
          "outlet": { "type": "string", "nullable": true },
          "storeId": { "type": "string", "nullable": true }
        },
        "required": ["id", "sku", "name", "price", "qty", "tax"]
      },
      "CartDelivery": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "provider": { "type": "string" },
          "price": { "type": "integer", "format": "int64" },
          "items": {
            "type": "array",
            "items": { "type": "integer" }
          },
          "pickupPoint": { "$ref": "#/components/schemas/PickupPoint" }
        },
        "required": ["id", "provider", "price", "items"]
      },
      "PickupPoint": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string", "nullable": true },
          "address": { "type": "string", "nullable": true },
          "city": { "type": "string", "nullable": true },
          "zip": { "type": "string", "nullable": true },
          "country": { "type": "string", "nullable": true }
        },
        "required": ["id"]
      },
      "AddRequest": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "format": "int32",
            "minimum": 1,
            "default": 1
          },
          "sku": { "type": "string" },
          "country": {
            "type": "string",
            "description": "Two-letter country code (inferred if omitted)"
          },
          "storeId": { "type": "string", "nullable": true }
        },
        "required": ["sku"]
      },
      "ChangeQuantity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Cart line item id"
          },
          "quantity": { "type": "integer", "format": "int32", "minimum": 0 }
        },
        "required": ["id", "quantity"]
      },
      "Item": {
        "type": "object",
        "properties": {
          "sku": { "type": "string" },
          "quantity": { "type": "integer", "minimum": 1 },
          "storeId": { "type": "string", "nullable": true }
        },
        "required": ["sku", "quantity"]
      },
      "SetCartItems": {
        "type": "object",
        "properties": {
          "country": { "type": "string" },
          "items": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Item" },
            "minItems": 0
          }
        },
        "required": ["items"]
      },
      "SetDeliveryRequest": {
        "type": "object",
        "properties": {
          "provider": { "type": "string" },
          "items": {
            "type": "array",
            "items": { "type": "integer", "format": "int64" },
            "description": "Line item ids served by this delivery"
          },
          "pickupPoint": { "$ref": "#/components/schemas/PickupPoint" }
        },
        "required": ["provider", "items"]
      },
      "AddVoucherRequest": {
        "type": "object",
        "properties": {
          "code": { "type": "string" }
        },
        "required": ["code"]
      },
      "UpsertSubscriptionDetails": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "offeringCode": { "type": "string" },
          "signingType": { "type": "string" },
          "data": { "type": "object" }
        },
        "required": ["offeringCode", "signingType"]
      },
      "Voucher": {
        "type": "object",
        "properties": {
          "code": { "type": "string" },
          "applied": { "type": "boolean" },
          "rules": {
            "type": "array",
            "items": { "type": "string" }
          },
          "description": { "type": "string" },
          "id": { "type": "integer", "format": "int64" },
          "value": { "type": "integer", "format": "int64" }
        },
        "required": ["code", "applied", "rules", "id", "value"]
      },
      "SubscriptionDetails": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "offeringCode": { "type": "string" },
          "signingType": { "type": "string" },
          "data": { "type": "object" }
        },
        "required": ["id"]
      }
    }
  },
  "tags": [{ "name": "Cart" }, { "name": "Delivery" }, { "name": "System" }]
}
