{
  "openapi": "3.1.0",
  "info": {
    "title": "CourierAPP Merchant API",
    "version": "0.6.10",
    "description": "Account-specific live quotes and merchant wallet shipping. FedEx EU-only with special territory exclusions. Automatic purchases GR to BE/NL/AT standard parcels only. Cancellation requests and settlement reports are available on the live endpoint; requests do not cancel carrier labels or refund funds automatically. Refund execution, paid BYOC and public Shopify distribution remain gated. Test PDFs and DEMO_EUR are not real shipping or money."
  },
  "servers": [
    {
      "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-api",
      "description": "Live: account prices and business-wallet purchase; shipment scope and billing agreement required"
    },
    {
      "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-api-sandbox",
      "description": "Sandbox: fixture prices, no real payments or carrier labels"
    }
  ],
  "security": [
    {
      "MerchantKey": []
    }
  ],
  "paths": {
    "/v1/capabilities": {
      "get": {
        "summary": "Account mode, carriers, purchase permission and automatic destination limits",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/quotes": {
      "post": {
        "summary": "Immutable merchant quote, valid for 15 minutes",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "quotes"
                  ],
                  "properties": {
                    "quotes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Quote"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              },
              "example": {
                "origin": {
                  "country": "GR",
                  "postal": "71601",
                  "city": "Heraklion"
                },
                "destination": {
                  "country": "BE",
                  "postal": "1000",
                  "city": "Brussels"
                },
                "packages": [
                  {
                    "weightKg": 1,
                    "lengthCm": 30,
                    "widthCm": 20,
                    "heightCm": 10
                  }
                ],
                "declaredValueEur": 50
              }
            }
          }
        }
      }
    },
    "/v1/shipments": {
      "post": {
        "summary": "Purchase postage for a confirmed paid store order once",
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Shipment"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient wallet balance; no order or debit committed"
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShipmentCommand"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_.:-]{8,160}$"
            },
            "description": "Stable per store/order/parcel. Persist command before sending. Retry unchanged; a changed payload is a conflict."
          }
        ],
        "description": "The buyer pays the shop. This endpoint debits the shop owner’s prepaid CourierAPP wallet, not the buyer’s payment provider. A new live purchase requires an eligible business account, explicit merchant-wallet-2026-10-12 agreement, valid account quote and sufficient balance. Persist one immutable request and Idempotency-Key per order/parcel. If outcome is unknown, reconcile by same identity; never submit a second parcel identity."
      }
    },
    "/v1/shipments/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Read an owned shipment",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Shipment"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/shipments/{id}/label": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Download base64 PDF, explicitly invalid for real shipping",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Label"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Returns authenticated JSON with mime_type and content_base64 (decode on the server), not raw PDF bytes. Sandbox labels are invalid for shipping. label_ready does not prove pickup, scan or delivery."
      }
    },
    "/v1/shipments/{id}/tracking": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Read tracking and pickup independently",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": " Returns tracking_url when unified customer tracking is enabled. Never builds customer links from arbitrary tracking numbers."
      }
    },
    "/v1/events": {
      "get": {
        "summary": "Poll owned lifecycle events with a durable cursor; up to 50",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "next_cursor": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "events",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing/invalid/revoked/expired key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Expired quote, changed retry, or label not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 64 KiB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unsupported lane or incomplete shipment data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "60 requests per store per minute exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "description": "Unavailable or live purchase disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,18}$",
              "default": "0"
            }
          }
        ],
        "description": "Persist the next_cursor string without numeric conversion. Deduplicate by event ID; assign one tracking notification sender."
      }
    },
    "/v1/quotes/{id}/validate": {
      "get": {
        "summary": "Revalidate quote and account price before payment",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Still valid; quote_id, total_cents, currency and expires_at"
          },
          "409": {
            "description": "Expired or changed account price; refresh before payment"
          }
        }
      }
    },
    "/v1/shipments/{id}/cancellation": {
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Record an owned cancellation request; no automatic carrier cancellation or refund",
        "description": "Live endpoint only. Keep the same reason and idempotency key on retries. A 202 acknowledgement records a request, not a completed cancellation. Unknown outcomes require reconciliation.",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_.:-]{8,160}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Cancellation request recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "shipment_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "state": {
                      "enum": [
                        "requested",
                        "processing",
                        "carrier_cancelled",
                        "refunded",
                        "rejected",
                        "reconciliation_required"
                      ]
                    },
                    "refund_cents": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "currency": {
                      "const": "EUR"
                    },
                    "error_code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Shipment write scope required"
          },
          "404": {
            "description": "Owned shipment not found"
          },
          "409": {
            "description": "Idempotency conflict"
          }
        }
      },
      "get": {
        "summary": "Read cancellation status for an owned shipment",
        "responses": {
          "200": {
            "description": "Current request state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "shipment_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "state": {
                      "enum": [
                        "requested",
                        "processing",
                        "carrier_cancelled",
                        "refunded",
                        "rejected",
                        "reconciliation_required"
                      ]
                    },
                    "refund_cents": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "currency": {
                      "const": "EUR"
                    },
                    "error_code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No owned cancellation request"
          }
        }
      }
    },
    "/v1/shipments/{id}/settlement": {
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Read owned shipment wallet debits, credits and reconciliation state",
        "description": "Live endpoint only. Does not create an invoice or refund the shopper payment. Amounts are integer EUR cents.",
        "responses": {
          "200": {
            "description": "Merchant wallet settlement report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "shipment_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "production_wallet": {
                      "type": "boolean"
                    },
                    "debit_cents": {
                      "type": "integer"
                    },
                    "refund_cents": {
                      "type": "integer"
                    },
                    "net_charge_cents": {
                      "type": "integer"
                    },
                    "currency": {
                      "const": "EUR"
                    },
                    "reconciliation_required": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Owned shipment not found"
          }
        }
      }
    },
    "/v1/subscription": {
      "get": {
        "summary": "Read own store subscription and shared account label quota",
        "responses": {
          "200": {
            "description": "Current server-verified entitlement",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environment": {
                      "enum": [
                        "test",
                        "live"
                      ]
                    },
                    "plan_id": {
                      "type": "string"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "used": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "limit": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "period_end": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "environment",
                    "plan_id",
                    "active",
                    "used",
                    "limit"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid merchant key"
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "summary": "Read SMS settings, balance and latest jobs",
        "description": "Requires shipments:read. Secrets and full phone numbers are never returned.",
        "servers": [
          {
            "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-sms",
            "description": "Isolated optional notification service; disabled until explicitly configured"
          }
        ],
        "tags": [
          "SMS"
        ],
        "security": [
          {
            "MerchantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Result. Preview never dispatches. Sync only queues a verified shipment event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/preview": {
      "post": {
        "summary": "Preview one SMS and its destination-specific cost",
        "description": "Requires shipments:read and shipments:write. Cost is expressed in micro-EUR: 1000000 = EUR1. No send is performed.",
        "servers": [
          {
            "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-sms",
            "description": "Isolated optional notification service; disabled until explicitly configured"
          }
        ],
        "tags": [
          "SMS"
        ],
        "security": [
          {
            "MerchantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone": {
                    "type": "string",
                    "pattern": "^\\+[1-9][0-9]{7,14}$"
                  },
                  "kind": {
                    "enum": [
                      "in_transit",
                      "out_for_delivery",
                      "delivered"
                    ]
                  },
                  "carrier": {
                    "type": "string"
                  },
                  "tracking": {
                    "type": "string"
                  }
                },
                "required": [
                  "phone",
                  "kind",
                  "carrier",
                  "tracking"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result. Preview never dispatches. Sync only queues a verified shipment event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/settings": {
      "post": {
        "summary": "Configure optional SMS for new shipments",
        "description": "Requires shipments:read and shipments:write. Live platform mode stays unavailable until enabled server-side. Sandbox simulates messages and cannot send real SMS. Only shipments created after opt-in qualify.",
        "servers": [
          {
            "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-sms",
            "description": "Isolated optional notification service; disabled until explicitly configured"
          }
        ],
        "tags": [
          "SMS"
        ],
        "security": [
          {
            "MerchantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "provider_mode": {
                    "enum": [
                      "byo",
                      "platform"
                    ]
                  },
                  "api_key": {
                    "type": "string",
                    "writeOnly": true,
                    "description": "Optional replacement Yuboto Base64 API key; omit to retain existing encrypted key"
                  },
                  "remove_key": {
                    "type": "boolean"
                  },
                  "sender_id": {
                    "type": "string",
                    "maxLength": 11
                  },
                  "locale": {
                    "enum": [
                      "el",
                      "en",
                      "de"
                    ]
                  },
                  "prefixes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[1-9][0-9]{0,3}$"
                    },
                    "minItems": 1,
                    "maxItems": 40
                  },
                  "kinds": {
                    "type": "array",
                    "items": {
                      "enum": [
                        "in_transit",
                        "out_for_delivery",
                        "delivered"
                      ]
                    },
                    "maxItems": 3
                  },
                  "max_segments": {
                    "const": 1
                  },
                  "message_cap_micros": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5000000
                  },
                  "monthly_cap_micros": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000000000
                  }
                },
                "required": [
                  "enabled",
                  "provider_mode",
                  "sender_id",
                  "locale",
                  "prefixes",
                  "kinds",
                  "max_segments",
                  "message_cap_micros",
                  "monthly_cap_micros"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result. Preview never dispatches. Sync only queues a verified shipment event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/sync": {
      "post": {
        "summary": "Queue an eligible physical shipment event once",
        "description": "Requires shipments:read and shipments:write. Shipment must belong to the authenticated store. This is not an arbitrary-number message sending endpoint. A label or payment alone never counts as a physical scan. Unknown provider outcomes are held without blind retry.",
        "servers": [
          {
            "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-sms",
            "description": "Isolated optional notification service; disabled until explicitly configured"
          }
        ],
        "tags": [
          "SMS"
        ],
        "security": [
          {
            "MerchantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shipment_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "shipment_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result. Preview never dispatches. Sync only queues a verified shipment event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request rejected without sending an SMS",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stores/{store_id}/carriers": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "List encrypted carrier connections and read-only verification date. Shipment activation remains gated.",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/carriers/couriercenter": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Save tenant-bound Courier Center API credentials; reset previous verification. No shipment created.",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "credentials"
                ],
                "properties": {
                  "credentials": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "UserAlias",
                      "CredentialValue",
                      "ApiKey",
                      "CarrierBillingAccount"
                    ],
                    "properties": {
                      "UserAlias": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500,
                        "writeOnly": true
                      },
                      "CredentialValue": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500,
                        "writeOnly": true
                      },
                      "ApiKey": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500,
                        "writeOnly": true
                      },
                      "CarrierBillingAccount": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500,
                        "writeOnly": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/carriers/couriercenter/verify": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Verify read-only access to an existing voucher on the connected carrier account. Does not enable shipment creation.",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tracking_number"
                ],
                "properties": {
                  "tracking_number": {
                    "type": "string",
                    "pattern": "^[0-9]{10,20}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/operations": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Plan, label/email/SMS balances, current configuration and latest workflow outcomes",
        "description": "Owner JWT for a specific store, or its scoped merchant API key. Read requires shipments:read; writes require shipments:write. Use the dashboard for the complete versioned configuration. No historical resend.",
        "security": [
          {
            "OwnerJWT": []
          },
          {
            "MerchantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/workflow": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Save per-store email templates, stages, caps and order status mapping",
        "description": "Owner JWT for a specific store, or its scoped merchant API key. Read requires shipments:read; writes require shipments:write. Use the dashboard for the complete versioned configuration. No historical resend.",
        "security": [
          {
            "OwnerJWT": []
          },
          {
            "MerchantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/workflow/preview": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Preview a configured email without sending",
        "description": "Owner JWT for a specific store, or its scoped merchant API key. Read requires shipments:read; writes require shipments:write. Use the dashboard for the complete versioned configuration. No historical resend.",
        "security": [
          {
            "OwnerJWT": []
          },
          {
            "MerchantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        }
      }
    },
    "/stores/{store_id}/carriers/couriercenter/tariff": {
      "get": {
        "summary": "Read or replace the owner-confirmed tax-inclusive postcode tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        }
      },
      "post": {
        "summary": "Read or replace the owner-confirmed tax-inclusive postcode tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Optional cod configuration requires explicit own-account opt-in, an agreed maximum and confirmation that COD fees are included. Defaults off."
      }
    },
    "/stores/{store_id}/carriers/couriercenter/activate": {
      "post": {
        "summary": "Enable this owner connection; global production gate still applies",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        }
      }
    },
    "/stores/{store_id}/carriers/speedex": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "SPEEDEX merchant-owned connection",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "credentials"
                ],
                "properties": {
                  "credentials": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "username",
                      "password",
                      "customer_id",
                      "agreement_id"
                    ],
                    "properties": {
                      "username": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "password": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "customer_id": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "agreement_id": {
                        "type": "string",
                        "writeOnly": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/speedex/verify": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "SPEEDEX merchant-owned connection/verify",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/speedex/tariff": {
      "get": {
        "summary": "SPEEDEX merchant-owned connection/tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      },
      "post": {
        "summary": "SPEEDEX merchant-owned connection/tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/speedex/activate": {
      "post": {
        "summary": "SPEEDEX merchant-owned connection/activate",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enable",
                  "account_is_mine"
                ],
                "properties": {
                  "enable": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "account_is_mine": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "production_account_confirmed": {
                    "type": "boolean",
                    "description": "Must be true for a live SPEEDEX/ACS store."
                  },
                  "manual_handover": {
                    "type": "boolean",
                    "description": "Must be true for a live SPEEDEX/ACS store. Pickup, and ACS manifest, are organized separately by the merchant."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stores/{store_id}/carriers/acs": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "ACS merchant-owned connection",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "credentials"
                ],
                "properties": {
                  "credentials": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "api_key",
                      "company_id",
                      "company_password",
                      "user_id",
                      "user_password",
                      "billing_code"
                    ],
                    "properties": {
                      "api_key": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "company_id": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "company_password": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "user_id": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "user_password": {
                        "type": "string",
                        "writeOnly": true
                      },
                      "billing_code": {
                        "type": "string",
                        "writeOnly": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/acs/verify": {
      "servers": [
        {
          "url": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations"
        }
      ],
      "parameters": [
        {
          "name": "store_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "ACS merchant-owned connection/verify",
        "security": [
          {
            "OwnerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Owner-scoped success. No credentials are returned."
          },
          "401": {
            "description": "Owner authentication required"
          },
          "403": {
            "description": "Ownership or active matching-environment subscription required"
          },
          "429": {
            "description": "Provider rate limit reached"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/acs/tariff": {
      "get": {
        "summary": "ACS merchant-owned connection/tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      },
      "post": {
        "summary": "ACS merchant-owned connection/tariff",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance."
      }
    },
    "/stores/{store_id}/carriers/acs/activate": {
      "post": {
        "summary": "ACS merchant-owned connection/activate",
        "parameters": [
          {
            "name": "store_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated owner result"
          },
          "403": {
            "description": "Owner or paid plan required"
          },
          "422": {
            "description": "Invalid tariff or activation confirmation"
          }
        },
        "description": "Sandbox uses synthetic data. Live requires the merchant's own production credentials, read-only verification, agreed tariff and explicit per-store activation. No pickup or account-wide manifest is created. ACS live cancellation requires ACS assistance.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enable",
                  "account_is_mine"
                ],
                "properties": {
                  "enable": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "account_is_mine": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "production_account_confirmed": {
                    "type": "boolean",
                    "description": "Must be true for a live SPEEDEX/ACS store."
                  },
                  "manual_handover": {
                    "type": "boolean",
                    "description": "Must be true for a live SPEEDEX/ACS store. Pickup, and ACS manifest, are organized separately by the merchant."
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "MerchantKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer ca_live_ or ca_test_ followed by 64 hex characters; only works against its matching endpoint. Generated by authenticated owner, stored hashed and shown once. Never expose to browser code."
      },
      "OwnerJWT": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Supabase user JWT"
      }
    },
    "schemas": {
      "Route": {
        "type": "object",
        "required": [
          "country",
          "postal",
          "city"
        ],
        "properties": {
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$"
          },
          "postal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40
          }
        }
      },
      "Contact": {
        "type": "object",
        "required": [
          "country",
          "postal",
          "city",
          "name",
          "address",
          "phone",
          "email"
        ],
        "properties": {
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$"
          },
          "postal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "address": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "phone": {
            "type": "string",
            "minLength": 1,
            "maxLength": 30,
            "pattern": "^[+0-9 ()-]{7,30}$"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          }
        }
      },
      "Package": {
        "type": "object",
        "required": [
          "weightKg",
          "lengthCm",
          "widthCm",
          "heightCm"
        ],
        "properties": {
          "weightKg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 1000
          },
          "lengthCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 500
          },
          "widthCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 500
          },
          "heightCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 500
          }
        }
      },
      "QuoteRequest": {
        "type": "object",
        "required": [
          "origin",
          "destination",
          "declaredValueEur"
        ],
        "properties": {
          "origin": {
            "$ref": "#/components/schemas/Route"
          },
          "destination": {
            "$ref": "#/components/schemas/Route"
          },
          "packages": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/Package"
            }
          },
          "declaredValueEur": {
            "type": "number",
            "minimum": 0,
            "maximum": 100000
          },
          "destination_locker_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40
          },
          "cart": {
            "$ref": "#/components/schemas/Cart"
          },
          "checkout_policy": {
            "$ref": "#/components/schemas/CheckoutPolicy"
          }
        },
        "description": "Only Greece origin. Domestic is explicit fixture pilot. Verified packed size/weight is required. Special goods, documents, insurance or nonstandard packaging need a separate reviewed flow.",
        "anyOf": [
          {
            "required": [
              "packages"
            ]
          },
          {
            "required": [
              "cart",
              "checkout_policy"
            ]
          }
        ]
      },
      "Quote": {
        "type": "object",
        "required": [
          "quote_id",
          "carrier",
          "service_code",
          "service_name",
          "total_cents",
          "currency",
          "tax_included",
          "expires_at",
          "mode"
        ],
        "properties": {
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "carrier": {
            "enum": [
              "dhl",
              "fedex",
              "acs",
              "boxnow"
            ]
          },
          "service_code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "service_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "total_cents": {
            "type": "integer",
            "minimum": 1
          },
          "currency": {
            "const": "EUR"
          },
          "tax_included": {
            "const": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "mode": {
            "enum": [
              "sandbox",
              "live"
            ]
          },
          "rate_source": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "estimated_business_days": {
            "type": [
              "object",
              "null"
            ]
          },
          "service_category": {
            "description": "Display classification only; availability and subscription access are enforced server-side.",
            "type": "string",
            "enum": [
              "international",
              "premium_express",
              "merchant_contract"
            ]
          },
          "cod": {
            "$ref": "#/components/schemas/CodConfiguration"
          },
          "checkout": {
            "type": "object",
            "readOnly": true,
            "description": "customer_shipping_cents is the final checkout charge. total_cents remains the merchant shipping charge. material_cents/store_cost_cents, actual_weight_kg/volumetric_weight_kg, matched_tier_id and verified box placements explain the selection. Never apply markup twice. Existing carrier account/scope/route gates still apply."
          },
          "packages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Package"
            },
            "readOnly": true,
            "description": "Chosen immutable packed parcels; retain quote_id for label creation."
          }
        }
      },
      "ShipmentRequest": {
        "type": "object",
        "properties": {
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "external_order_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "parcel_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "payment": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "status": {
                    "const": "paid"
                  },
                  "reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  }
                },
                "required": [
                  "status",
                  "reference"
                ]
              },
              {
                "$ref": "#/components/schemas/CodPayment"
              }
            ],
            "description": "COD only for a verified own-account Courier Center contract with explicit COD opt-in, GR–GR and exactly one parcel. Delivery never means payment confirmation."
          },
          "sender": {
            "$ref": "#/components/schemas/Contact"
          },
          "recipient": {
            "$ref": "#/components/schemas/Contact"
          },
          "pickup": {
            "type": "object",
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "description": "Future weekday, at most 14 days, Europe/Athens. Existing identical receipt remains retryable afterward."
              },
              "window": {
                "type": "string",
                "pattern": "^\\d{2}:\\d{2}-\\d{2}:\\d{2}$",
                "description": "Start before end; within 08:00–18:00."
              }
            },
            "required": [
              "date",
              "window"
            ]
          },
          "content_description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "customs_exempt": {
            "const": true,
            "description": "Does not override server lane eligibility. Automatic sandbox destinations GR/BE/NL/AT only."
          },
          "terms": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "accepted_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "version",
              "accepted_at"
            ]
          }
        },
        "required": [
          "quote_id",
          "external_order_id",
          "parcel_reference",
          "payment",
          "sender",
          "recipient",
          "pickup",
          "content_description",
          "customs_exempt",
          "terms"
        ],
        "description": "Confirmed shop-payment assertion authenticated by the merchant key. It does not claim a payment to CourierAPP. Live postage is settled separately and atomically from the merchant wallet. Automatic live destinations: BE/NL/AT, origin GR. GR domestic exists only in explicit sandbox fixture tests."
      },
      "Label": {
        "type": "object",
        "properties": {
          "mime_type": {
            "const": "application/pdf"
          },
          "content_base64": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "mode": {
            "enum": [
              "sandbox",
              "live"
            ]
          },
          "valid_for_shipping": {
            "type": "boolean",
            "description": "Always false in sandbox. A live PDF is a label, not proof of physical collection."
          }
        },
        "required": [
          "mime_type",
          "content_base64",
          "mode",
          "valid_for_shipping"
        ]
      },
      "Shipment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_order_id": {
            "type": "string"
          },
          "parcel_reference": {
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "processing",
              "label_ready",
              "action_required",
              "reconciliation_required",
              "cancelled"
            ]
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "tracking": {
            "type": [
              "object",
              "null"
            ]
          },
          "label": {
            "type": [
              "object",
              "null"
            ],
            "description": "Provider label metadata. Use authenticated GET /v1/shipments/{id}/label for validated PDF bytes. Null until ready."
          },
          "pickup": {
            "type": [
              "object",
              "null"
            ]
          },
          "tracking_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "readOnly": true,
            "description": "Private, expiring customer capability link on https://track.courierapp.gr. Treat as sensitive; do not log, index or publicly share. Only when enabled; does not imply physical movement."
          }
        },
        "required": [
          "id",
          "external_order_id",
          "parcel_reference",
          "status",
          "order_id",
          "error_code",
          "tracking",
          "label",
          "pickup"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "code",
              "request_id"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ShipmentCommand": {
        "type": "object",
        "required": [
          "quote_id",
          "external_order_id",
          "parcel_reference",
          "payment",
          "sender",
          "recipient",
          "pickup",
          "content_description",
          "customs_exempt",
          "terms"
        ],
        "properties": {
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "external_order_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "parcel_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "payment": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "status": {
                    "const": "paid"
                  },
                  "reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150
                  }
                },
                "required": [
                  "status",
                  "reference"
                ]
              },
              {
                "$ref": "#/components/schemas/CodPayment"
              }
            ],
            "description": "COD only for a verified own-account Courier Center contract with explicit COD opt-in, GR–GR and exactly one parcel. Delivery never means payment confirmation."
          },
          "sender": {
            "$ref": "#/components/schemas/Contact"
          },
          "recipient": {
            "$ref": "#/components/schemas/Contact"
          },
          "pickup": {
            "type": "object",
            "required": [
              "date",
              "window"
            ],
            "properties": {
              "date": {
                "type": "string",
                "format": "date",
                "description": "Future weekday within 14 days, Europe/Athens. Identical existing receipts can be reconciled after this date."
              },
              "window": {
                "type": "string",
                "pattern": "^[0-2][0-9]:[0-5][0-9]-[0-2][0-9]:[0-5][0-9]$",
                "description": "Start before end, between 08:00 and 18:00."
              }
            }
          },
          "content_description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "customs_exempt": {
            "const": true,
            "description": "Required assertion, never overrides server-owned lane and commodity rules."
          },
          "terms": {
            "type": "object",
            "required": [
              "version",
              "accepted_at"
            ],
            "properties": {
              "version": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "accepted_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        "description": "Confirmed shop-payment assertion authenticated by the merchant key. It does not claim a payment to CourierAPP. Live postage is settled separately and atomically from the merchant wallet. Automatic live destinations: BE/NL/AT, origin GR. GR domestic exists only in explicit sandbox fixture tests."
      },
      "CodPayment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "method",
          "currency",
          "amount_cents",
          "reference"
        ],
        "properties": {
          "status": {
            "const": "pending"
          },
          "method": {
            "const": "cod"
          },
          "currency": {
            "const": "EUR"
          },
          "amount_cents": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000000,
            "description": "Full unpaid order total in cents, including taxes/shipping/fees; must not exceed the merchant COD limit."
          },
          "reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150
          }
        }
      },
      "CodConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "enabled",
          "fee_included",
          "max_amount_cents"
        ],
        "properties": {
          "enabled": {
            "const": true
          },
          "fee_included": {
            "const": true,
            "description": "Merchant confirms COD fees are included in the configured tariff."
          },
          "max_amount_cents": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000000
          }
        }
      },
      "Cart": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 40,
            "items": {
              "type": "object",
              "required": [
                "name",
                "quantity",
                "weight",
                "dimensions",
                "line_total_cents"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "maxLength": 120
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 40
                },
                "weight": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "Single product kg"
                },
                "dimensions": {
                  "type": "array",
                  "minItems": 3,
                  "maxItems": 3,
                  "items": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 200
                  },
                  "description": "Single product L/W/H cm"
                },
                "rotation": {
                  "enum": [
                    "all",
                    "upright",
                    "fixed"
                  ]
                },
                "noStack": {
                  "type": "boolean"
                },
                "line_total_cents": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Discounted physical line total including applicable tax; not unit price."
                }
              }
            }
          }
        }
      },
      "CheckoutPolicy": {
        "type": "object",
        "required": [
          "version",
          "carriers"
        ],
        "properties": {
          "version": {
            "const": 1
          },
          "packing": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "paddingMm": {
                "type": "number",
                "minimum": 0,
                "maximum": 50
              },
              "boxes": {
                "type": "array",
                "maxItems": 8,
                "items": {
                  "$ref": "#/components/schemas/PackingBox"
                }
              }
            }
          },
          "carriers": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/CheckoutCarrierRule"
            }
          }
        },
        "description": "Server-to-server, opt-in. Merchant boxes must match real stock. Missing dimensions/weight fail closed. Existing lane, goods, account, billing and pickup gates remain unchanged."
      },
      "PackingBox": {
        "type": "object",
        "required": [
          "id",
          "inner",
          "outer",
          "tare",
          "maxKg",
          "materialCents"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "inner": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "items": {
              "type": "number"
            },
            "description": "Internal L/W/H cm"
          },
          "outer": {
            "type": "array",
            "minItems": 3,
            "maxItems": 3,
            "items": {
              "type": "number"
            },
            "description": "External L/W/H cm"
          },
          "tare": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Empty box kg"
          },
          "maxKg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 1000
          },
          "materialCents": {
            "type": "integer",
            "minimum": 0
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "CheckoutCarrierRule": {
        "type": "object",
        "required": [
          "enabled",
          "mode",
          "value",
          "includeMaterials"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "mode": {
            "enum": [
              "actual",
              "percent",
              "markup",
              "fixed"
            ]
          },
          "value": {
            "type": "number",
            "minimum": 0
          },
          "includeMaterials": {
            "type": "boolean"
          },
          "minimumCents": {
            "type": "integer",
            "minimum": 0
          },
          "freeTiers": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/FreeShippingTier"
            }
          }
        }
      },
      "FreeShippingTier": {
        "type": "object",
        "required": [
          "id",
          "enabled",
          "zone",
          "minCartCents",
          "maxWeightKg",
          "weightBasis",
          "maxCostCents",
          "maxCostPercent"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "zone": {
            "enum": [
              "GR",
              "EU",
              "NON_EU"
            ]
          },
          "minCartCents": {
            "type": "integer",
            "minimum": 1
          },
          "maxWeightKg": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "weightBasis": {
            "enum": [
              "max",
              "actual",
              "volume",
              "billable"
            ]
          },
          "maxCostCents": {
            "type": "integer",
            "minimum": 0
          },
          "maxCostPercent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          }
        },
        "description": "AND within each tier; OR across matching-zone tiers. max uses greater aggregate actual/volume kg. Unknown weight does not qualify. Zero cost cap is unlimited; store absorbs postage and materials."
      },
      "MarketingConsent": {
        "type": "object",
        "required": [
          "email",
          "channel",
          "granted",
          "explicit_action",
          "source",
          "reference"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "channel": {
            "const": "email"
          },
          "granted": {
            "type": "boolean"
          },
          "explicit_action": {
            "const": true
          },
          "source": {
            "type": "string",
            "minLength": 3,
            "maxLength": 120
          },
          "reference": {
            "type": "string",
            "minLength": 3,
            "maxLength": 160
          }
        },
        "description": "Server-only explicit consent evidence. Stable reference per actual user action. Never infer consent from a purchase, account creation or a prechecked field. Withdrawal blocks promotions; necessary shipment notifications continue."
      }
    }
  },
  "x-self-service": {
    "portal": "https://courierapp.gr/connect/account",
    "base": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations",
    "flow": [
      "POST /connections: platform, origin_url, name, challenge = SHA256(32-byte hex verifier)",
      "GET /connections/{id}: public pairing code/domain/status (10-minute expiry)",
      "POST /connections/{id}/approve: verified owner JWT, matching code, explicit mode and live wallet agreement",
      "POST /connections/{id}/exchange: server-only verifier; single-use key response",
      "DELETE /stores/{store_id}/keys/{id}: verified owner JWT revokes only owned store key"
    ],
    "security": "Never place verifier, owner JWT, or returned API key in URL or browser storage. Match displayed pairing code and shop domain before approval. Supports password login and TOTP MFA."
  },
  "x-merchant-integrations-marketing": {
    "base": "https://swdjgtbhifglgnnmwthf.supabase.co/functions/v1/merchant-integrations",
    "path": "/stores/self/marketing-consent",
    "method": "POST",
    "security": "Store bearer key with shipments:write; never expose in checkout browser. Owner JWT can address owned store UUID.",
    "request_schema": "#/components/schemas/MarketingConsent",
    "unsubscribe": "Opaque signed/encrypted capability. GET confirmation only; POST revokes, including RFC 8058 one-click. No login required.",
    "shopify": "Use the protected custom integration only with independently verified explicit consent. Shopify order purchase is never assumed to be marketing consent."
  }
}
