{
  "components": {
    "schemas": {
      "ApiErrorResponseDto": {
        "properties": {
          "error": {
            "description": "Same as errorCode",
            "example": "DUPLICATE_ORDER_ID",
            "type": "string"
          },
          "errorCode": {
            "description": "Machine-readable, extensible code. Known values: ADYEN_REFUSED, CARD_DATA_NOT_ACCEPTED, RATE_LIMITED, PAYMENT_LINK_INVALID_AMOUNT, PAYMENT_LINK_UNSUPPORTED_CURRENCY, PAYMENT_LINK_INVALID_EXPIRY, PAYMENT_LINK_INVALID_MAX_USES, PAYMENT_LINK_REDIRECT_URL_NOT_ALLOWED, PAYMENT_LINK_METADATA_TOO_LARGE, PAYMENT_LINK_INVALID_TEXT, PAYMENT_LINK_NOT_FOUND, PAYMENT_LINK_INVALID_LIMIT, PAYMENT_LINK_INVALID_CURSOR, API_KEY_ROTATION_REQUIRED, ORDER_ID_RESERVED, NO_CREDENTIALS_FOR_MODE, LIVEMODE_MISMATCH, PSP_OUTCOME_UNKNOWN, PAYMENT_METHOD_REQUIRED, PAYMENT_METHOD_INPUT_WITHOUT_METHOD, NO_PAYMENT_METHODS, IDEMPOTENCY_KEY_INVALID, DUPLICATE_ORDER_ID, IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_KEY_REUSED, UPSTREAM_ERROR, UPSTREAM_UNAVAILABLE, UPSTREAM_TIMEOUT, REFUND_INVALID_AMOUNT, REFUND_INVALID_REASON, REFUND_INVALID_METADATA, REFUND_INPUT_INVALID, REFUND_EXCEEDS_AMOUNT, TRANSACTION_NOT_REFUNDABLE, REFUND_NOT_FOUND, REFUND_NOT_SUPPORTED, IDEMPOTENCY_LEASE_LOST, REFUND_SERVICE_UNAVAILABLE. New codes may be added; clients must handle unknown values.",
            "example": "DUPLICATE_ORDER_ID",
            "type": "string"
          },
          "existingTransactionId": {
            "description": "DUPLICATE_ORDER_ID only: the transaction that already uses this orderId",
            "example": "tr_x8k2p0q5scocndpejk0nud75q",
            "type": "string"
          },
          "fields": {
            "description": "Invalid or missing buyer contact fields for CUSTOMER_CONTACT_REQUIRED",
            "example": ["customer.email", "customer.country"],
            "items": { "type": "string" },
            "type": "array"
          },
          "idempotencyKey": {
            "description": "IDEMPOTENCY_* errors only",
            "example": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
            "type": "string"
          },
          "message": {
            "example": "A transaction with orderId \"A-1001\" already exists for this merchant",
            "type": "string"
          },
          "orderId": {
            "description": "DUPLICATE_ORDER_ID only",
            "example": "A-1001",
            "type": "string"
          },
          "status": { "example": false, "type": "boolean" },
          "statusCode": { "example": 409, "type": "number" }
        },
        "required": ["status", "statusCode", "errorCode", "error", "message"],
        "type": "object"
      },
      "AuthenticationUnavailableResponseDto": {
        "properties": {
          "error": { "example": "Service Unavailable", "type": "string" },
          "message": {
            "example": "API_KEY_VALIDATION_UNAVAILABLE",
            "type": "string"
          },
          "statusCode": { "example": 503, "type": "number" }
        },
        "required": ["statusCode", "error", "message"],
        "type": "object"
      },
      "CashierCreateSessionDto": {
        "properties": {
          "binding": { "$ref": "#/components/schemas/CashierPlayerBindingDto" },
          "country": { "type": "string" },
          "expiresAt": { "type": "string" },
          "locale": { "type": "string" },
          "metadata": { "type": "object" },
          "orderId": { "type": "string" }
        },
        "required": ["binding", "orderId"],
        "type": "object"
      },
      "CashierDepositDto": {
        "properties": {
          "amount": {
            "example": "25.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": { "example": "EUR", "type": "string" },
          "expectedTotal": {
            "example": "25.50",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "fields": { "type": "object" },
          "methodChoiceId": { "type": "string" },
          "quoteId": { "type": "string" }
        },
        "required": [
          "methodChoiceId",
          "amount",
          "currency",
          "expectedTotal",
          "quoteId"
        ],
        "type": "object"
      },
      "CashierGrantResponseDto": {
        "properties": {
          "accessToken": {
            "description": "Opaque player grant, never a merchant API key. Keep only in memory.",
            "type": "string"
          },
          "expiresAt": { "format": "date-time", "type": "string" },
          "generation": { "minimum": 1, "type": "integer" },
          "instanceId": { "type": "string" },
          "serverTime": { "format": "date-time", "type": "string" },
          "sessionId": { "type": "string" }
        },
        "required": [
          "sessionId",
          "instanceId",
          "accessToken",
          "expiresAt",
          "serverTime",
          "generation"
        ],
        "type": "object"
      },
      "CashierMintGrantDto": {
        "properties": {
          "binding": { "$ref": "#/components/schemas/CashierPlayerBindingDto" },
          "instanceId": { "type": "string" }
        },
        "required": ["binding", "instanceId"],
        "type": "object"
      },
      "CashierPlayerBindingDto": {
        "properties": {
          "currency": { "example": "EUR", "type": "string" },
          "launchMode": {
            "enum": ["embedded", "standalone"],
            "type": "string"
          },
          "operatorLoginSessionId": { "type": "string" },
          "parentOrigin": {
            "example": "https://casino.example",
            "type": "string"
          },
          "playerId": { "maxLength": 100, "minLength": 1, "type": "string" }
        },
        "required": [
          "playerId",
          "operatorLoginSessionId",
          "currency",
          "parentOrigin",
          "launchMode"
        ],
        "type": "object"
      },
      "CashierQuoteDto": {
        "properties": {
          "amount": {
            "example": "25.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": { "example": "EUR", "type": "string" },
          "fields": { "type": "object" },
          "methodChoiceId": { "type": "string" }
        },
        "required": ["methodChoiceId", "amount", "currency"],
        "type": "object"
      },
      "CashierQuoteResponseDto": {
        "properties": {
          "amount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "configRevision": { "type": "string" },
          "currency": { "type": "string" },
          "expiresAt": { "format": "date-time", "type": "string" },
          "fee": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "id": { "type": "string" },
          "methodChoiceId": { "type": "string" },
          "total": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "methodChoiceId",
          "amount",
          "fee",
          "total",
          "currency",
          "expiresAt",
          "configRevision"
        ],
        "type": "object"
      },
      "CashierRevokeSessionDto": {
        "properties": {
          "binding": { "$ref": "#/components/schemas/CashierPlayerBindingDto" }
        },
        "required": ["binding"],
        "type": "object"
      },
      "CashierWalletReceiptDto": {
        "properties": {
          "amount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": { "type": "string" },
          "effectId": { "type": "string" },
          "eventId": { "type": "string" },
          "kind": {
            "enum": ["credit", "capture", "release"],
            "type": "string"
          },
          "livemode": { "type": "boolean" },
          "operationId": { "type": "string" },
          "orderId": { "type": "string" },
          "playerId": { "maxLength": 100, "type": "string" },
          "revision": { "type": "string" },
          "simulation": {
            "description": "Exact stored effect simulation flag. Simulation is test-mode only and never activates real wallet money.",
            "type": "boolean"
          },
          "transactionId": {
            "description": "Real engine transaction; omission is allowed only for pre-dispatch release.",
            "type": "string"
          },
          "walletOperationId": { "type": "string" }
        },
        "required": [
          "effectId",
          "eventId",
          "walletOperationId",
          "operationId",
          "orderId",
          "playerId",
          "livemode",
          "simulation",
          "amount",
          "currency",
          "kind",
          "revision"
        ],
        "type": "object"
      },
      "CreatePaymentLinkRequestDto": {
        "properties": {
          "amount": {
            "description": "Positive decimal string in major units, within the currency exponent.",
            "example": "12.34",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": { "example": "EUR", "type": "string" },
          "description": {
            "example": "Order payment",
            "maxLength": 500,
            "type": "string"
          },
          "expiresAt": {
            "description": "ISO-8601 timestamp with explicit Z or ±hh:mm offset.",
            "format": "date-time",
            "type": "string"
          },
          "failureUrl": {
            "example": "https://shop.example.com/failure",
            "maxLength": 2048,
            "type": "string"
          },
          "maxUses": {
            "description": "Defaults to 1 for a single-use link; unlimited when reusable and omitted.",
            "maximum": 1000000,
            "minimum": 1,
            "type": "number"
          },
          "metadata": {
            "additionalProperties": true,
            "description": "JSON object, at most 16 KiB.",
            "type": "object"
          },
          "reusable": { "default": false, "type": "boolean" },
          "successUrl": {
            "example": "https://shop.example.com/success",
            "maxLength": 2048,
            "type": "string"
          }
        },
        "required": ["amount", "currency"],
        "type": "object"
      },
      "CreateRefundDto": {
        "properties": {
          "amount": {
            "description": "Positive decimal string in the payment currency, within its currency precision. Omit to refund the remaining refundable amount.",
            "example": "10.00",
            "maxLength": 80,
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "metadata": {
            "additionalProperties": true,
            "description": "JSON object, at most 16384 UTF-8 bytes when serialized; maximum container depth 10 (root depth 0). Do not include sensitive customer or payment data.",
            "type": "object"
          },
          "reason": {
            "default": "requested_by_customer",
            "enum": [
              "requested_by_customer",
              "duplicate",
              "fraudulent",
              "other"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "CryptoIssueDto": {
        "properties": {
          "amount": {
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "expectedTotal": {
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "fields": {
            "description": "Omit or pass an empty object; native crypto has no payer fields.",
            "maxProperties": 0,
            "type": "object"
          },
          "methodChoiceId": { "type": "string" },
          "optionChoiceId": { "type": "string" },
          "quoteId": { "type": "string" }
        },
        "required": [
          "methodChoiceId",
          "optionChoiceId",
          "amount",
          "currency",
          "expectedTotal",
          "quoteId"
        ],
        "type": "object"
      },
      "CryptoQuoteDto": {
        "properties": {
          "amount": {
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "pattern": "^[A-Z]{3}$",
            "type": "string"
          },
          "fields": {
            "description": "Omit or pass an empty object; native crypto has no payer fields.",
            "maxProperties": 0,
            "type": "object"
          },
          "methodChoiceId": { "type": "string" },
          "optionChoiceId": { "type": "string" }
        },
        "required": ["methodChoiceId", "optionChoiceId", "amount", "currency"],
        "type": "object"
      },
      "CustomerDto": {
        "properties": {
          "address": {
            "description": "Customer address",
            "example": "123 Main St",
            "type": "string"
          },
          "address2": {
            "description": "Customer address2",
            "example": "Apt 1",
            "type": "string"
          },
          "city": {
            "description": "Customer city",
            "example": "Anytown",
            "type": "string"
          },
          "country": {
            "description": "Customer ISO alpha-2 country code; Adyen requires uppercase, Brite accepts either case. Provider-specific missing/invalid contact returns 422 CUSTOMER_CONTACT_REQUIRED.",
            "enum": [
              "AD",
              "ad",
              "AE",
              "ae",
              "AF",
              "af",
              "AG",
              "ag",
              "AI",
              "ai",
              "AL",
              "al",
              "AM",
              "am",
              "AN",
              "an",
              "AO",
              "ao",
              "AQ",
              "aq",
              "AR",
              "ar",
              "AS",
              "as",
              "AT",
              "at",
              "AU",
              "au",
              "AW",
              "aw",
              "AX",
              "ax",
              "AZ",
              "az",
              "BA",
              "ba",
              "BB",
              "bb",
              "BD",
              "bd",
              "BE",
              "be",
              "BF",
              "bf",
              "BG",
              "bg",
              "BH",
              "bh",
              "BI",
              "bi",
              "BJ",
              "bj",
              "BL",
              "bl",
              "BM",
              "bm",
              "BN",
              "bn",
              "BO",
              "bo",
              "BQ",
              "bq",
              "BR",
              "br",
              "BS",
              "bs",
              "BT",
              "bt",
              "BV",
              "bv",
              "BW",
              "bw",
              "BY",
              "by",
              "BZ",
              "bz",
              "CA",
              "ca",
              "CC",
              "cc",
              "CD",
              "cd",
              "CF",
              "cf",
              "CG",
              "cg",
              "CH",
              "ch",
              "CI",
              "ci",
              "CK",
              "ck",
              "CL",
              "cl",
              "CM",
              "cm",
              "CN",
              "cn",
              "CO",
              "co",
              "CR",
              "cr",
              "CU",
              "cu",
              "CV",
              "cv",
              "CW",
              "cw",
              "CX",
              "cx",
              "CY",
              "cy",
              "CZ",
              "cz",
              "DE",
              "de",
              "DJ",
              "dj",
              "DK",
              "dk",
              "DM",
              "dm",
              "DO",
              "do",
              "DZ",
              "dz",
              "EC",
              "ec",
              "EE",
              "ee",
              "EG",
              "eg",
              "EH",
              "eh",
              "ER",
              "er",
              "ES",
              "es",
              "ET",
              "et",
              "FI",
              "fi",
              "FJ",
              "fj",
              "FK",
              "fk",
              "FM",
              "fm",
              "FO",
              "fo",
              "FR",
              "fr",
              "GA",
              "ga",
              "GB",
              "gb",
              "GD",
              "gd",
              "GE",
              "ge",
              "GF",
              "gf",
              "GG",
              "gg",
              "GH",
              "gh",
              "GI",
              "gi",
              "GL",
              "gl",
              "GM",
              "gm",
              "GN",
              "gn",
              "GP",
              "gp",
              "GQ",
              "gq",
              "GR",
              "gr",
              "GS",
              "gs",
              "GT",
              "gt",
              "GU",
              "gu",
              "GW",
              "gw",
              "GY",
              "gy",
              "HK",
              "hk",
              "HM",
              "hm",
              "HN",
              "hn",
              "HR",
              "hr",
              "HT",
              "ht",
              "HU",
              "hu",
              "ID",
              "id",
              "IE",
              "ie",
              "IL",
              "il",
              "IM",
              "im",
              "IN",
              "in",
              "IO",
              "io",
              "IQ",
              "iq",
              "IR",
              "ir",
              "IS",
              "is",
              "IT",
              "it",
              "JE",
              "je",
              "JM",
              "jm",
              "JO",
              "jo",
              "JP",
              "jp",
              "KE",
              "ke",
              "KG",
              "kg",
              "KH",
              "kh",
              "KI",
              "ki",
              "KM",
              "km",
              "KN",
              "kn",
              "KP",
              "kp",
              "KR",
              "kr",
              "KW",
              "kw",
              "KY",
              "ky",
              "KZ",
              "kz",
              "LA",
              "la",
              "LB",
              "lb",
              "LC",
              "lc",
              "LI",
              "li",
              "LK",
              "lk",
              "LR",
              "lr",
              "LS",
              "ls",
              "LT",
              "lt",
              "LU",
              "lu",
              "LV",
              "lv",
              "LY",
              "ly",
              "MA",
              "ma",
              "MC",
              "mc",
              "MD",
              "md",
              "ME",
              "me",
              "MF",
              "mf",
              "MG",
              "mg",
              "MH",
              "mh",
              "MK",
              "mk",
              "ML",
              "ml",
              "MM",
              "mm",
              "MN",
              "mn",
              "MO",
              "mo",
              "MP",
              "mp",
              "MQ",
              "mq",
              "MR",
              "mr",
              "MS",
              "ms",
              "MT",
              "mt",
              "MU",
              "mu",
              "MV",
              "mv",
              "MW",
              "mw",
              "MX",
              "mx",
              "MY",
              "my",
              "MZ",
              "mz",
              "NA",
              "na",
              "NC",
              "nc",
              "NE",
              "ne",
              "NF",
              "nf",
              "NG",
              "ng",
              "NI",
              "ni",
              "NL",
              "nl",
              "NO",
              "no",
              "NP",
              "np",
              "NR",
              "nr",
              "NU",
              "nu",
              "NZ",
              "nz",
              "OM",
              "om",
              "PA",
              "pa",
              "PE",
              "pe",
              "PF",
              "pf",
              "PG",
              "pg",
              "PH",
              "ph",
              "PK",
              "pk",
              "PL",
              "pl",
              "PM",
              "pm",
              "PN",
              "pn",
              "PR",
              "pr",
              "PS",
              "ps",
              "PT",
              "pt",
              "PW",
              "pw",
              "PY",
              "py",
              "QA",
              "qa",
              "RE",
              "re",
              "RO",
              "ro",
              "RS",
              "rs",
              "RU",
              "ru",
              "RW",
              "rw",
              "SA",
              "sa",
              "SB",
              "sb",
              "SC",
              "sc",
              "SD",
              "sd",
              "SE",
              "se",
              "SG",
              "sg",
              "SH",
              "sh",
              "SI",
              "si",
              "SJ",
              "sj",
              "SK",
              "sk",
              "SL",
              "sl",
              "SM",
              "sm",
              "SN",
              "sn",
              "SO",
              "so",
              "SR",
              "sr",
              "SS",
              "ss",
              "ST",
              "st",
              "SV",
              "sv",
              "SX",
              "sx",
              "SY",
              "sy",
              "SZ",
              "sz",
              "TC",
              "tc",
              "TD",
              "td",
              "TF",
              "tf",
              "TG",
              "tg",
              "TH",
              "th",
              "TJ",
              "tj",
              "TK",
              "tk",
              "TL",
              "tl",
              "TM",
              "tm",
              "TN",
              "tn",
              "TO",
              "to",
              "TR",
              "tr",
              "TT",
              "tt",
              "TV",
              "tv",
              "TW",
              "tw",
              "TZ",
              "tz",
              "UA",
              "ua",
              "UG",
              "ug",
              "UM",
              "um",
              "US",
              "us",
              "UY",
              "uy",
              "UZ",
              "uz",
              "VA",
              "va",
              "VC",
              "vc",
              "VE",
              "ve",
              "VG",
              "vg",
              "VI",
              "vi",
              "VN",
              "vn",
              "VU",
              "vu",
              "WF",
              "wf",
              "WS",
              "ws",
              "YE",
              "ye",
              "YT",
              "yt",
              "ZA",
              "za",
              "ZM",
              "zm",
              "ZW",
              "zw"
            ],
            "example": "US",
            "type": "string"
          },
          "dob": {
            "description": "Customer date of birth",
            "example": "1990-01-01T00:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "email": {
            "description": "Customer email",
            "example": "test@test.com",
            "type": "string"
          },
          "firstName": {
            "description": "Customer first name",
            "example": "John",
            "type": "string"
          },
          "ip": {
            "description": "Customer IP",
            "example": "123.45.67.89",
            "type": "string"
          },
          "lastName": {
            "description": "Customer last name",
            "example": "Doe",
            "type": "string"
          },
          "phone": {
            "description": "Customer phone",
            "example": "+1234567890",
            "type": "string"
          },
          "state": {
            "description": "Customer state",
            "example": "CA",
            "type": "string"
          },
          "userAgent": {
            "description": "Customer user agent",
            "example": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
            "type": "string"
          },
          "zip": {
            "description": "Customer zip",
            "example": "12345",
            "type": "string"
          }
        },
        "type": "object"
      },
      "MerchantTransactionDto": {
        "properties": {
          "action": {
            "description": "Transaction action type",
            "enum": ["SALE", "PAYOUT", "AUTHORIZE", "REFUND", "CHARGEBACK"],
            "example": "SALE",
            "type": "string"
          },
          "amount": {
            "description": "Transaction amount in `currency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "createdAt": {
            "description": "Transaction creation timestamp",
            "example": "2023-12-25T10:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "Transaction currency",
            "enum": [
              "AED",
              "AFN",
              "ALL",
              "AMD",
              "ANG",
              "AOA",
              "ARS",
              "AUD",
              "AWG",
              "AZN",
              "BAM",
              "BBD",
              "BDT",
              "BGN",
              "BHD",
              "BIF",
              "BMD",
              "BND",
              "BOB",
              "BRL",
              "BSD",
              "BTN",
              "BWP",
              "BYN",
              "BZD",
              "CAD",
              "CDF",
              "CHF",
              "CLF",
              "CLP",
              "CNY",
              "COP",
              "CRC",
              "CUC",
              "CUP",
              "CVE",
              "CZK",
              "DJF",
              "DKK",
              "DOP",
              "DZD",
              "EGP",
              "ERN",
              "ETB",
              "EUR",
              "FJD",
              "FKP",
              "GBP",
              "GEL",
              "GHS",
              "GIP",
              "GMD",
              "GNF",
              "GTQ",
              "GYD",
              "HKD",
              "HNL",
              "HRK",
              "HTG",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "IQD",
              "IRR",
              "ISK",
              "JMD",
              "JOD",
              "JPY",
              "KES",
              "KGS",
              "KHR",
              "KMF",
              "KPW",
              "KRW",
              "KWD",
              "KYD",
              "KZT",
              "LAK",
              "LBP",
              "LKR",
              "LRD",
              "LSL",
              "LYD",
              "MAD",
              "MDL",
              "MGA",
              "MKD",
              "MMK",
              "MNT",
              "MOP",
              "MRU",
              "MUR",
              "MVR",
              "MWK",
              "MXN",
              "MYR",
              "MZN",
              "NAD",
              "NGN",
              "NIO",
              "NOK",
              "NPR",
              "NZD",
              "OMR",
              "PAB",
              "PEN",
              "PGK",
              "PHP",
              "PKR",
              "PLN",
              "PYG",
              "QAR",
              "RON",
              "RSD",
              "RUB",
              "RWF",
              "SAR",
              "SBD",
              "SCR",
              "SDG",
              "SEK",
              "SGD",
              "SHP",
              "SLL",
              "SOS",
              "SRD",
              "SSP",
              "STN",
              "SVC",
              "SYP",
              "SZL",
              "THB",
              "TJS",
              "TMT",
              "TND",
              "TOP",
              "TRY",
              "TTD",
              "TWD",
              "TZS",
              "UAH",
              "UGX",
              "USD",
              "UYU",
              "UZS",
              "VES",
              "VND",
              "VUV",
              "WST",
              "XAF",
              "XAG",
              "XAU",
              "XCD",
              "XDR",
              "XOF",
              "XPF",
              "YER",
              "ZAR",
              "ZMW",
              "ZWL"
            ],
            "example": "USD",
            "type": "string"
          },
          "errorCode": {
            "anyOf": [
              {
                "description": "Payment error/outcome reason. LIVEMODE_MISMATCH means the transaction was DECLINED before PSP dispatch; creation still returns HTTP 201 with status: true. PSP_OUTCOME_UNKNOWN means reconcile or poll; do not create another order. PSP_INPUT_INVALID identifies local legacy-submit serialization/codec failures; PSP_REQUEST_REJECTED identifies a definitive upstream rejection.",
                "example": "PSP_OUTCOME_UNKNOWN",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "id": {
            "description": "Transaction ID",
            "example": "tr_xv0p2q5scocndpejk0nud75q",
            "type": "string"
          },
          "livemode": {
            "description": "True for live payments; false for sandbox payments. Derived from the authenticated API key.",
            "example": true,
            "type": "boolean"
          },
          "orderId": {
            "description": "Order ID from merchant system",
            "example": "transaction_123",
            "type": "string"
          },
          "processingAmount": {
            "anyOf": [
              {
                "description": "Amount in `processingCurrency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
                "example": "9.57",
                "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "processingCurrency": {
            "description": "Currency the PSP is charged in (differs from `currency` with DCC)",
            "enum": [
              "AED",
              "AFN",
              "ALL",
              "AMD",
              "ANG",
              "AOA",
              "ARS",
              "AUD",
              "AWG",
              "AZN",
              "BAM",
              "BBD",
              "BDT",
              "BGN",
              "BHD",
              "BIF",
              "BMD",
              "BND",
              "BOB",
              "BRL",
              "BSD",
              "BTN",
              "BWP",
              "BYN",
              "BZD",
              "CAD",
              "CDF",
              "CHF",
              "CLF",
              "CLP",
              "CNY",
              "COP",
              "CRC",
              "CUC",
              "CUP",
              "CVE",
              "CZK",
              "DJF",
              "DKK",
              "DOP",
              "DZD",
              "EGP",
              "ERN",
              "ETB",
              "EUR",
              "FJD",
              "FKP",
              "GBP",
              "GEL",
              "GHS",
              "GIP",
              "GMD",
              "GNF",
              "GTQ",
              "GYD",
              "HKD",
              "HNL",
              "HRK",
              "HTG",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "IQD",
              "IRR",
              "ISK",
              "JMD",
              "JOD",
              "JPY",
              "KES",
              "KGS",
              "KHR",
              "KMF",
              "KPW",
              "KRW",
              "KWD",
              "KYD",
              "KZT",
              "LAK",
              "LBP",
              "LKR",
              "LRD",
              "LSL",
              "LYD",
              "MAD",
              "MDL",
              "MGA",
              "MKD",
              "MMK",
              "MNT",
              "MOP",
              "MRU",
              "MUR",
              "MVR",
              "MWK",
              "MXN",
              "MYR",
              "MZN",
              "NAD",
              "NGN",
              "NIO",
              "NOK",
              "NPR",
              "NZD",
              "OMR",
              "PAB",
              "PEN",
              "PGK",
              "PHP",
              "PKR",
              "PLN",
              "PYG",
              "QAR",
              "RON",
              "RSD",
              "RUB",
              "RWF",
              "SAR",
              "SBD",
              "SCR",
              "SDG",
              "SEK",
              "SGD",
              "SHP",
              "SLL",
              "SOS",
              "SRD",
              "SSP",
              "STN",
              "SVC",
              "SYP",
              "SZL",
              "THB",
              "TJS",
              "TMT",
              "TND",
              "TOP",
              "TRY",
              "TTD",
              "TWD",
              "TZS",
              "UAH",
              "UGX",
              "USD",
              "UYU",
              "UZS",
              "VES",
              "VND",
              "VUV",
              "WST",
              "XAF",
              "XAG",
              "XAU",
              "XCD",
              "XDR",
              "XOF",
              "XPF",
              "YER",
              "ZAR",
              "ZMW",
              "ZWL"
            ],
            "example": "EUR",
            "type": "string"
          },
          "status": {
            "description": "Transaction status",
            "enum": [
              "CREATED",
              "WAIT_APPROVE",
              "PROCESSING",
              "CANCELED",
              "DECLINED",
              "SUCCESS",
              "EXPIRED"
            ],
            "example": "PROCESSING",
            "type": "string"
          }
        },
        "required": [
          "livemode",
          "id",
          "orderId",
          "status",
          "action",
          "amount",
          "currency",
          "createdAt"
        ],
        "type": "object"
      },
      "PaymentLinkResponseDto": {
        "properties": {
          "amount": {
            "example": "12.34",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "example": "EUR", "type": "string" },
          "description": {
            "anyOf": [{ "type": "string" }, { "type": "null" }]
          },
          "expired": { "type": "boolean" },
          "expiresAt": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "failureUrl": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
          "id": {
            "example": "pl_01j9a6d6dqevssvyw7s97pkrga",
            "type": "string"
          },
          "isActive": { "type": "boolean" },
          "livemode": {
            "description": "The live/test mode inherited from the authenticated API key.",
            "example": true,
            "type": "boolean"
          },
          "maxUses": { "anyOf": [{ "type": "number" }, { "type": "null" }] },
          "merchantId": { "type": "string" },
          "metadata": { "additionalProperties": true, "type": "object" },
          "reusable": { "type": "boolean" },
          "slug": { "pattern": "^[A-Za-z0-9]{24}$", "type": "string" },
          "status": {
            "enum": ["ACTIVE", "INACTIVE", "EXPIRED", "EXHAUSTED"],
            "type": "string"
          },
          "successUrl": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
          "url": {
            "anyOf": [
              {
                "description": "Null when hosted checkout is disabled.",
                "example": "https://pay.example.com/l/aBcDeFgHiJkLmNoPqRsTuVwX",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "usesCount": { "type": "number" }
        },
        "required": [
          "livemode",
          "id",
          "merchantId",
          "slug",
          "amount",
          "currency",
          "description",
          "reusable",
          "maxUses",
          "usesCount",
          "expiresAt",
          "successUrl",
          "failureUrl",
          "metadata",
          "isActive",
          "expired",
          "status",
          "createdAt",
          "url"
        ],
        "type": "object"
      },
      "PaymentLinksResponseDto": {
        "properties": {
          "data": {
            "items": { "$ref": "#/components/schemas/PaymentLinkResponseDto" },
            "type": "array"
          },
          "nextCursor": { "anyOf": [{ "type": "string" }, { "type": "null" }] }
        },
        "required": ["data", "nextCursor"],
        "type": "object"
      },
      "PaymentListResponseDto": {
        "properties": {
          "data": {
            "items": { "$ref": "#/components/schemas/MerchantTransactionDto" },
            "type": "array"
          },
          "has_more": { "example": false, "type": "boolean" },
          "next_cursor": {
            "anyOf": [
              {
                "description": "Pass as starting_after for the next page",
                "example": null,
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "status": { "example": true, "type": "boolean" }
        },
        "required": ["status", "data", "has_more", "next_cursor"],
        "type": "object"
      },
      "PaymentResponseDto": {
        "properties": {
          "error": {
            "description": "Error message (if operation failed)",
            "example": "Payment method not available",
            "type": "string"
          },
          "nextAction": {
            "description": "Validated app confirmation or voucher instructions for the payer",
            "type": "object"
          },
          "paymentPageUrl": {
            "description": "Sales only: the hosted payment page, when the buyer still has to pick a method or type payment details (no `paymentMethod`, or incomplete `paymentMethodInput`). Redirect the buyer there; `url` carries the same value. Valid until the sale expires (48 h by default); the token in it is the only key to the page, so treat the URL like a secret link.",
            "example": "https://pay.example.com/pay/hpp1.dHJfeHYwcDJxNXNjb2NuZHBlamswbnVkNzVxOjE3NjAxMDAwMDA.X8f…",
            "type": "string"
          },
          "pending": {
            "description": "Accepted payment awaiting confirmation. On PSP_OUTCOME_UNKNOWN poll the transaction; do not resubmit or create a new order.",
            "example": true,
            "type": "boolean"
          },
          "status": {
            "description": "Operation status",
            "example": true,
            "type": "boolean"
          },
          "transaction": {
            "allOf": [{ "$ref": "#/components/schemas/TransactionDto" }],
            "description": "Transaction details"
          },
          "url": {
            "description": "Redirect URL for payment completion (if required)",
            "example": "https://payment-provider.com/pay/abc123",
            "type": "string"
          }
        },
        "required": ["status"],
        "type": "object"
      },
      "PayoutRequestDto": {
        "properties": {
          "amount": {
            "description": "Amount as a decimal **string** in **major** units of `currency`: `\"12.30\"` EUR, `\"5000\"` JPY, `\"0.00000001\"` BTC. Must be greater than zero. JSON numbers (`12.3`, `1230`) are rejected with 400. At most 18 decimals here; the payment core also rejects more decimals than the currency allows (`\"12.345\"` EUR, `\"1.5\"` JPY).",
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "buyerId": {
            "description": "Buyer ID in merchant system",
            "example": "customer_123",
            "type": "string"
          },
          "callbackUrl": {
            "description": "Callback URL",
            "example": "https://example.com/callback",
            "type": "string"
          },
          "currency": {
            "description": "Currency",
            "example": "USD",
            "type": "string"
          },
          "customer": {
            "allOf": [{ "$ref": "#/components/schemas/CustomerDto" }],
            "description": "Customer",
            "example": {
              "address": "123 Main St",
              "address2": "Apt 1",
              "city": "Anytown",
              "country": "US",
              "dob": "1990-01-01",
              "email": "test@test.com",
              "firstName": "John",
              "ip": "123.45.67.89",
              "lastName": "Doe",
              "phone": "+1234567890",
              "state": "CA",
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
              "zip": "12345"
            }
          },
          "failureUrl": {
            "description": "Failure URL",
            "example": "https://example.com/failure",
            "type": "string"
          },
          "locale": {
            "description": "Locale in BCP 47 format",
            "enum": [
              "en-US",
              "ru-RU",
              "uk-UA",
              "en-GB",
              "pl-PL",
              "cs-CZ",
              "de-DE",
              "de-AT",
              "de-CH"
            ],
            "example": "en-US",
            "type": "string"
          },
          "merchantId": {
            "description": "Merchant ID",
            "example": "mr_clyv2goxb0000z8b8j5y6fl1j",
            "type": "string"
          },
          "metadata": {
            "description": "Metadata: at most 16 KiB encoded JSON, 50 entries per container, nesting depth 5.",
            "example": {},
            "maxProperties": 50,
            "type": "object"
          },
          "orderId": {
            "description": "Transaction ID in merchant system. The pl_ prefix is reserved for payment links (422 ORDER_ID_RESERVED).",
            "example": "transaction_123",
            "type": "string"
          },
          "paymentMethod": {
            "description": "Payment method",
            "example": "cr_clyv2goxb0000z8b8j5y6fl1j",
            "type": "string"
          },
          "paymentMethodInput": {
            "description": "Payment method input",
            "example": {},
            "type": "object"
          },
          "returnUrl": {
            "description": "Return URL",
            "example": "https://example.com/return",
            "type": "string"
          },
          "sourceTransactionId": {
            "description": "Required for Colibrix payouts: OrsunPay ID of a successful card sale belonging to the same merchant, customer, payment configuration and mode",
            "example": "tr_source",
            "maxLength": 128,
            "type": "string"
          },
          "successUrl": {
            "description": "Success URL",
            "example": "https://example.com/success",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency",
          "paymentMethod",
          "merchantId",
          "orderId",
          "buyerId",
          "successUrl",
          "failureUrl",
          "returnUrl",
          "callbackUrl"
        ],
        "type": "object"
      },
      "RefundDto": {
        "properties": {
          "amount": {
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "example": "EUR", "type": "string" },
          "errorCode": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
          "id": { "example": "rf_example", "type": "string" },
          "metadata": { "additionalProperties": true, "type": "object" },
          "providerRefundId": {
            "anyOf": [{ "type": "string" }, { "type": "null" }]
          },
          "reason": {
            "enum": [
              "requested_by_customer",
              "duplicate",
              "fraudulent",
              "other"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "PENDING",
              "PROCESSING",
              "SUCCEEDED",
              "FAILED",
              "CANCELED"
            ],
            "type": "string"
          },
          "transactionId": { "example": "tr_example", "type": "string" },
          "updatedAt": { "format": "date-time", "type": "string" }
        },
        "required": [
          "id",
          "transactionId",
          "amount",
          "currency",
          "status",
          "reason",
          "providerRefundId",
          "errorCode",
          "metadata",
          "createdAt",
          "updatedAt"
        ],
        "type": "object"
      },
      "RefundResponseDto": {
        "properties": { "data": { "$ref": "#/components/schemas/RefundDto" } },
        "required": ["data"],
        "type": "object"
      },
      "RefundWebhookEvent": {
        "description": "Immutable refund terminal event. Amounts use currency precision; retain the maximum refundedAmount when events arrive out of order.",
        "properties": {
          "api_version": {
            "example": "2026-10-31",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
            "type": "string"
          },
          "created": {
            "description": "Alias of created_at, preserved across retries.",
            "format": "date-time",
            "type": "string"
          },
          "created_at": { "format": "date-time", "type": "string" },
          "data": {
            "properties": {
              "refund": {
                "properties": {
                  "amount": {
                    "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                    "type": "string"
                  },
                  "currency": { "type": "string" },
                  "errorCode": {
                    "oneOf": [{ "type": "string" }, { "type": "null" }]
                  },
                  "id": { "type": "string" },
                  "provider": { "type": "string" },
                  "providerRefundId": {
                    "oneOf": [{ "type": "string" }, { "type": "null" }]
                  },
                  "reason": {
                    "enum": [
                      "requested_by_customer",
                      "duplicate",
                      "fraudulent",
                      "other"
                    ],
                    "type": "string"
                  },
                  "status": {
                    "enum": ["SUCCEEDED", "FAILED"],
                    "type": "string"
                  },
                  "transactionId": { "type": "string" }
                },
                "required": [
                  "id",
                  "transactionId",
                  "amount",
                  "currency",
                  "status",
                  "reason",
                  "provider",
                  "providerRefundId",
                  "errorCode"
                ],
                "type": "object"
              },
              "transaction": {
                "properties": {
                  "amount": {
                    "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                    "type": "string"
                  },
                  "id": { "type": "string" },
                  "livemode": { "type": "boolean" },
                  "orderId": { "type": "string" },
                  "refundState": {
                    "enum": ["none", "partial", "full"],
                    "type": "string"
                  },
                  "refundedAmount": {
                    "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "orderId",
                  "amount",
                  "refundedAmount",
                  "refundState",
                  "livemode"
                ],
                "type": "object"
              }
            },
            "required": ["refund", "transaction"],
            "type": "object"
          },
          "id": {
            "pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$",
            "type": "string"
          },
          "livemode": {
            "description": "Mode of the transaction snapshot; false for sandbox.",
            "type": "boolean"
          },
          "type": {
            "enum": ["refund.succeeded", "refund.failed"],
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "api_version",
          "created_at",
          "created",
          "data",
          "livemode"
        ],
        "type": "object"
      },
      "RefundsResponseDto": {
        "properties": {
          "data": {
            "items": { "$ref": "#/components/schemas/RefundDto" },
            "type": "array"
          },
          "nextCursor": { "anyOf": [{ "type": "string" }, { "type": "null" }] }
        },
        "required": ["data", "nextCursor"],
        "type": "object"
      },
      "SaleRequestDto": {
        "properties": {
          "amount": {
            "description": "Amount as a decimal **string** in **major** units of `currency`: `\"12.30\"` EUR, `\"5000\"` JPY, `\"0.00000001\"` BTC. Must be greater than zero. JSON numbers (`12.3`, `1230`) are rejected with 400. At most 18 decimals here; the payment core also rejects more decimals than the currency allows (`\"12.345\"` EUR, `\"1.5\"` JPY).",
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "buyerId": {
            "description": "Buyer ID in merchant system",
            "example": "customer_123",
            "type": "string"
          },
          "callbackUrl": {
            "description": "Callback URL",
            "example": "https://example.com/callback",
            "type": "string"
          },
          "currency": {
            "description": "Currency",
            "example": "USD",
            "type": "string"
          },
          "customer": {
            "allOf": [{ "$ref": "#/components/schemas/CustomerDto" }],
            "description": "Customer",
            "example": {
              "address": "123 Main St",
              "address2": "Apt 1",
              "city": "Anytown",
              "country": "US",
              "dob": "1990-01-01",
              "email": "test@test.com",
              "firstName": "John",
              "ip": "123.45.67.89",
              "lastName": "Doe",
              "phone": "+1234567890",
              "state": "CA",
              "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
              "zip": "12345"
            }
          },
          "description": {
            "description": "Order description shown to the buyer on the hosted payment page",
            "example": "2 x Coffee beans, 1 kg",
            "maxLength": 255,
            "type": "string"
          },
          "failureUrl": {
            "description": "Failure URL",
            "example": "https://example.com/failure",
            "type": "string"
          },
          "locale": {
            "description": "Locale in BCP 47 format",
            "enum": [
              "en-US",
              "ru-RU",
              "uk-UA",
              "en-GB",
              "pl-PL",
              "cs-CZ",
              "de-DE",
              "de-AT",
              "de-CH"
            ],
            "example": "en-US",
            "type": "string"
          },
          "merchantId": {
            "description": "Merchant ID",
            "example": "mr_clyv2goxb0000z8b8j5y6fl1j",
            "type": "string"
          },
          "metadata": {
            "description": "Metadata: at most 16 KiB encoded JSON, 50 entries per container, nesting depth 5.",
            "example": {},
            "maxProperties": 50,
            "type": "object"
          },
          "orderId": {
            "description": "Transaction ID in merchant system. The pl_ prefix is reserved for payment links (422 ORDER_ID_RESERVED).",
            "example": "transaction_123",
            "type": "string"
          },
          "paymentMethod": {
            "description": "Payment method (credential config id). Omit it to let the buyer pick one of your methods on the hosted payment page: the response then carries `paymentPageUrl`.",
            "example": "cr_clyv2goxb0000z8b8j5y6fl1j",
            "type": "string"
          },
          "paymentMethodInput": {
            "description": "Payment method input",
            "example": {},
            "type": "object"
          },
          "returnUrl": {
            "description": "Return URL",
            "example": "https://example.com/return",
            "type": "string"
          },
          "successUrl": {
            "description": "Success URL",
            "example": "https://example.com/success",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency",
          "merchantId",
          "orderId",
          "buyerId",
          "successUrl",
          "failureUrl",
          "returnUrl",
          "callbackUrl"
        ],
        "type": "object"
      },
      "TransactionDto": {
        "properties": {
          "action": {
            "description": "Transaction action type",
            "enum": ["SALE", "PAYOUT", "AUTHORIZE", "REFUND", "CHARGEBACK"],
            "example": "SALE",
            "type": "string"
          },
          "amount": {
            "description": "Transaction amount in `currency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
            "example": "10.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "createdAt": {
            "description": "Transaction creation timestamp",
            "example": "2023-12-25T10:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "Transaction currency",
            "enum": [
              "AED",
              "AFN",
              "ALL",
              "AMD",
              "ANG",
              "AOA",
              "ARS",
              "AUD",
              "AWG",
              "AZN",
              "BAM",
              "BBD",
              "BDT",
              "BGN",
              "BHD",
              "BIF",
              "BMD",
              "BND",
              "BOB",
              "BRL",
              "BSD",
              "BTN",
              "BWP",
              "BYN",
              "BZD",
              "CAD",
              "CDF",
              "CHF",
              "CLF",
              "CLP",
              "CNY",
              "COP",
              "CRC",
              "CUC",
              "CUP",
              "CVE",
              "CZK",
              "DJF",
              "DKK",
              "DOP",
              "DZD",
              "EGP",
              "ERN",
              "ETB",
              "EUR",
              "FJD",
              "FKP",
              "GBP",
              "GEL",
              "GHS",
              "GIP",
              "GMD",
              "GNF",
              "GTQ",
              "GYD",
              "HKD",
              "HNL",
              "HRK",
              "HTG",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "IQD",
              "IRR",
              "ISK",
              "JMD",
              "JOD",
              "JPY",
              "KES",
              "KGS",
              "KHR",
              "KMF",
              "KPW",
              "KRW",
              "KWD",
              "KYD",
              "KZT",
              "LAK",
              "LBP",
              "LKR",
              "LRD",
              "LSL",
              "LYD",
              "MAD",
              "MDL",
              "MGA",
              "MKD",
              "MMK",
              "MNT",
              "MOP",
              "MRU",
              "MUR",
              "MVR",
              "MWK",
              "MXN",
              "MYR",
              "MZN",
              "NAD",
              "NGN",
              "NIO",
              "NOK",
              "NPR",
              "NZD",
              "OMR",
              "PAB",
              "PEN",
              "PGK",
              "PHP",
              "PKR",
              "PLN",
              "PYG",
              "QAR",
              "RON",
              "RSD",
              "RUB",
              "RWF",
              "SAR",
              "SBD",
              "SCR",
              "SDG",
              "SEK",
              "SGD",
              "SHP",
              "SLL",
              "SOS",
              "SRD",
              "SSP",
              "STN",
              "SVC",
              "SYP",
              "SZL",
              "THB",
              "TJS",
              "TMT",
              "TND",
              "TOP",
              "TRY",
              "TTD",
              "TWD",
              "TZS",
              "UAH",
              "UGX",
              "USD",
              "UYU",
              "UZS",
              "VES",
              "VND",
              "VUV",
              "WST",
              "XAF",
              "XAG",
              "XAU",
              "XCD",
              "XDR",
              "XOF",
              "XPF",
              "YER",
              "ZAR",
              "ZMW",
              "ZWL"
            ],
            "example": "USD",
            "type": "string"
          },
          "currencyRate": {
            "anyOf": [
              {
                "description": "Effective DCC rate as a plain decimal string; null without DCC.",
                "example": "0.9573935814433348",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "errorCode": {
            "anyOf": [
              {
                "description": "Payment error/outcome reason. LIVEMODE_MISMATCH means the transaction was DECLINED before PSP dispatch; creation still returns HTTP 201 with status: true. PSP_OUTCOME_UNKNOWN means reconcile or poll; do not create another order. PSP_INPUT_INVALID identifies local legacy-submit serialization/codec failures; PSP_REQUEST_REJECTED identifies a definitive upstream rejection.",
                "example": "PSP_OUTCOME_UNKNOWN",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "feeAmount": {
            "anyOf": [
              {
                "description": "Configured fee: money in `processingCurrency` for FIXED fees, a percent (\"10\" = 10 %) for PERCENTAGE fees. Decimal string.",
                "example": "10",
                "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "id": {
            "description": "Transaction ID",
            "example": "tr_xv0p2q5scocndpejk0nud75q",
            "type": "string"
          },
          "livemode": {
            "description": "True for live payments; false for sandbox payments. Derived from the authenticated API key.",
            "example": true,
            "type": "boolean"
          },
          "orderId": {
            "description": "Order ID from merchant system",
            "example": "transaction_123",
            "type": "string"
          },
          "processingAmount": {
            "anyOf": [
              {
                "description": "Amount in `processingCurrency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
                "example": "9.57",
                "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "processingAmountWithFee": {
            "anyOf": [
              {
                "description": "Processing amount including a TOP fee, in `processingCurrency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
                "example": "10.53",
                "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "processingCurrency": {
            "description": "Currency the PSP is charged in (differs from `currency` with DCC)",
            "enum": [
              "AED",
              "AFN",
              "ALL",
              "AMD",
              "ANG",
              "AOA",
              "ARS",
              "AUD",
              "AWG",
              "AZN",
              "BAM",
              "BBD",
              "BDT",
              "BGN",
              "BHD",
              "BIF",
              "BMD",
              "BND",
              "BOB",
              "BRL",
              "BSD",
              "BTN",
              "BWP",
              "BYN",
              "BZD",
              "CAD",
              "CDF",
              "CHF",
              "CLF",
              "CLP",
              "CNY",
              "COP",
              "CRC",
              "CUC",
              "CUP",
              "CVE",
              "CZK",
              "DJF",
              "DKK",
              "DOP",
              "DZD",
              "EGP",
              "ERN",
              "ETB",
              "EUR",
              "FJD",
              "FKP",
              "GBP",
              "GEL",
              "GHS",
              "GIP",
              "GMD",
              "GNF",
              "GTQ",
              "GYD",
              "HKD",
              "HNL",
              "HRK",
              "HTG",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "IQD",
              "IRR",
              "ISK",
              "JMD",
              "JOD",
              "JPY",
              "KES",
              "KGS",
              "KHR",
              "KMF",
              "KPW",
              "KRW",
              "KWD",
              "KYD",
              "KZT",
              "LAK",
              "LBP",
              "LKR",
              "LRD",
              "LSL",
              "LYD",
              "MAD",
              "MDL",
              "MGA",
              "MKD",
              "MMK",
              "MNT",
              "MOP",
              "MRU",
              "MUR",
              "MVR",
              "MWK",
              "MXN",
              "MYR",
              "MZN",
              "NAD",
              "NGN",
              "NIO",
              "NOK",
              "NPR",
              "NZD",
              "OMR",
              "PAB",
              "PEN",
              "PGK",
              "PHP",
              "PKR",
              "PLN",
              "PYG",
              "QAR",
              "RON",
              "RSD",
              "RUB",
              "RWF",
              "SAR",
              "SBD",
              "SCR",
              "SDG",
              "SEK",
              "SGD",
              "SHP",
              "SLL",
              "SOS",
              "SRD",
              "SSP",
              "STN",
              "SVC",
              "SYP",
              "SZL",
              "THB",
              "TJS",
              "TMT",
              "TND",
              "TOP",
              "TRY",
              "TTD",
              "TWD",
              "TZS",
              "UAH",
              "UGX",
              "USD",
              "UYU",
              "UZS",
              "VES",
              "VND",
              "VUV",
              "WST",
              "XAF",
              "XAG",
              "XAU",
              "XCD",
              "XDR",
              "XOF",
              "XPF",
              "YER",
              "ZAR",
              "ZMW",
              "ZWL"
            ],
            "example": "EUR",
            "type": "string"
          },
          "processingFeeAmount": {
            "anyOf": [
              {
                "description": "Fee charged, in `processingCurrency`. Decimal string in major units, padded to the currency exponent (\"10.00\" EUR, \"5000\" JPY). Parse with a decimal library, never with parseFloat.",
                "example": "0.96",
                "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
                "type": "string"
              },
              { "type": "null" }
            ]
          },
          "status": {
            "description": "Transaction status",
            "enum": [
              "CREATED",
              "WAIT_APPROVE",
              "PROCESSING",
              "CANCELED",
              "DECLINED",
              "SUCCESS",
              "EXPIRED"
            ],
            "example": "PROCESSING",
            "type": "string"
          }
        },
        "required": [
          "livemode",
          "id",
          "orderId",
          "status",
          "action",
          "amount",
          "currency",
          "createdAt"
        ],
        "type": "object"
      },
      "TransactionNotFoundResponseDto": {
        "properties": {
          "error": { "example": "Not Found", "type": "string" },
          "message": { "example": "Transaction not found", "type": "string" },
          "statusCode": { "example": 404, "type": "number" }
        },
        "required": ["statusCode", "error", "message"],
        "type": "object"
      },
      "TransactionStatusResponseDto": {
        "properties": {
          "status": { "example": true, "type": "boolean" },
          "transaction": {
            "$ref": "#/components/schemas/MerchantTransactionDto"
          }
        },
        "required": ["status", "transaction"],
        "type": "object"
      },
      "UnauthorizedErrorResponseDto": {
        "properties": {
          "error": { "example": "Unauthorized", "type": "string" },
          "errorCode": {
            "description": "Stable authentication error code when available",
            "example": "API_KEY_ROTATION_REQUIRED",
            "type": "string"
          },
          "message": { "example": "Invalid API key", "type": "string" },
          "statusCode": {
            "description": "HTTP status when included by the error handler",
            "example": 401,
            "type": "number"
          }
        },
        "required": ["message"],
        "type": "object"
      },
      "UsageAttemptResponseDto": {
        "properties": {
          "amount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "attemptCount": { "type": "number" },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "type": "string" },
          "errorCode": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
          "id": { "type": "string" },
          "invoiceId": { "type": "string" },
          "status": { "type": "string" },
          "updatedAt": { "format": "date-time", "type": "string" }
        },
        "required": [
          "id",
          "invoiceId",
          "status",
          "amount",
          "currency",
          "attemptCount",
          "errorCode",
          "createdAt",
          "updatedAt"
        ],
        "type": "object"
      },
      "UsageAutoRenewConfirmDto": {
        "properties": { "setupId": { "type": "string" } },
        "required": ["setupId"],
        "type": "object"
      },
      "UsageAutoRenewSetupDto": {
        "properties": {
          "cancelUrl": { "format": "uri", "type": "string" },
          "credentialConfigId": { "type": "string" },
          "successUrl": { "format": "uri", "type": "string" }
        },
        "required": ["credentialConfigId", "successUrl", "cancelUrl"],
        "type": "object"
      },
      "UsageEmptyDto": { "properties": {}, "type": "object" },
      "UsageEventCreateDto": {
        "properties": {
          "credits": { "type": "string" },
          "eventId": { "type": "string" },
          "subscriptionId": { "type": "string" }
        },
        "required": ["subscriptionId", "eventId", "credits"],
        "type": "object"
      },
      "UsageEventResponseDto": {
        "properties": {
          "createdAt": { "format": "date-time", "type": "string" },
          "credits": { "type": "string" },
          "eventId": { "type": "string" },
          "id": { "type": "string" },
          "subscriptionId": { "type": "string" }
        },
        "required": ["id", "eventId", "subscriptionId", "credits", "createdAt"],
        "type": "object"
      },
      "UsageInvoiceResponseDto": {
        "properties": {
          "baseAmount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "type": "string" },
          "id": { "type": "string" },
          "kind": { "enum": ["initial", "renewal", "final"], "type": "string" },
          "overageAmount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "paidAt": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "paymentUrl": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
          "periodEnd": { "format": "date-time", "type": "string" },
          "periodStart": { "format": "date-time", "type": "string" },
          "status": { "enum": ["open", "paid", "void"], "type": "string" },
          "subscriptionId": { "type": "string" },
          "totalAmount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "subscriptionId",
          "kind",
          "status",
          "currency",
          "baseAmount",
          "overageAmount",
          "totalAmount",
          "periodStart",
          "periodEnd",
          "paymentUrl",
          "createdAt",
          "paidAt"
        ],
        "type": "object"
      },
      "UsageNotificationsDto": {
        "properties": {
          "email": {
            "description": "Required when notifications are enabled. The address is not echoed in responses.",
            "format": "email",
            "type": "string"
          },
          "enabled": { "type": "boolean" },
          "locale": { "enum": ["en", "uk"], "type": "string" }
        },
        "required": ["enabled", "locale"],
        "type": "object"
      },
      "UsagePlanCreateDto": {
        "properties": {
          "code": { "type": "string" },
          "currency": { "type": "string" },
          "includedCredits": { "type": "string" },
          "monthlyPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "name": { "type": "string" },
          "overageUnitPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "unit": { "type": "string" }
        },
        "required": [
          "code",
          "name",
          "unit",
          "currency",
          "monthlyPrice",
          "includedCredits",
          "overageUnitPrice"
        ],
        "type": "object"
      },
      "UsagePlanResponseDto": {
        "properties": {
          "code": { "type": "string" },
          "currency": { "type": "string" },
          "id": { "type": "string" },
          "includedCredits": { "type": "string" },
          "monthlyPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "name": { "type": "string" },
          "overageUnitPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "unit": { "type": "string" }
        },
        "required": [
          "id",
          "code",
          "name",
          "unit",
          "currency",
          "monthlyPrice",
          "includedCredits",
          "overageUnitPrice"
        ],
        "type": "object"
      },
      "UsageSetupResponseDto": {
        "properties": {
          "setupId": { "type": "string" },
          "status": { "type": "string" },
          "url": { "format": "uri", "type": "string" }
        },
        "required": ["setupId", "url", "status"],
        "type": "object"
      },
      "UsageSubscriptionCreateDto": {
        "properties": {
          "customerRef": { "type": "string" },
          "overageLimit": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "planId": { "type": "string" }
        },
        "required": ["planId", "customerRef", "overageLimit"],
        "type": "object"
      },
      "UsageSubscriptionDetailResponseDto": {
        "properties": {
          "autoRenewEnabled": { "type": "boolean" },
          "cancelAtPeriodEnd": { "type": "boolean" },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "type": "string" },
          "customerRef": { "type": "string" },
          "events": {
            "items": { "$ref": "#/components/schemas/UsageEventResponseDto" },
            "type": "array"
          },
          "id": { "type": "string" },
          "includedCredits": { "type": "string" },
          "invoices": {
            "items": { "$ref": "#/components/schemas/UsageInvoiceResponseDto" },
            "type": "array"
          },
          "monthlyPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "notificationEmailConfigured": { "type": "boolean" },
          "notificationEnabled": { "type": "boolean" },
          "notificationLocale": { "enum": ["en", "uk"], "type": "string" },
          "overageAmount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "overageCredits": { "type": "string" },
          "overageLimit": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "overageUnitPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "paymentState": {
            "description": "Payment state; unknown cannot be retried as a new payment.",
            "type": "string"
          },
          "periodEnd": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "periodStart": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "planId": { "type": "string" },
          "planName": { "type": "string" },
          "remainingCredits": { "type": "string" },
          "status": {
            "enum": ["pending_payment", "active", "past_due", "cancelled"],
            "type": "string"
          },
          "unit": { "type": "string" },
          "usedCredits": { "type": "string" }
        },
        "required": [
          "id",
          "planId",
          "customerRef",
          "status",
          "planName",
          "unit",
          "currency",
          "monthlyPrice",
          "includedCredits",
          "overageUnitPrice",
          "overageLimit",
          "periodStart",
          "periodEnd",
          "usedCredits",
          "remainingCredits",
          "overageCredits",
          "overageAmount",
          "cancelAtPeriodEnd",
          "autoRenewEnabled",
          "paymentState",
          "notificationEnabled",
          "notificationEmailConfigured",
          "notificationLocale",
          "createdAt",
          "events",
          "invoices"
        ],
        "type": "object"
      },
      "UsageSubscriptionResponseDto": {
        "properties": {
          "autoRenewEnabled": { "type": "boolean" },
          "cancelAtPeriodEnd": { "type": "boolean" },
          "createdAt": { "format": "date-time", "type": "string" },
          "currency": { "type": "string" },
          "customerRef": { "type": "string" },
          "id": { "type": "string" },
          "includedCredits": { "type": "string" },
          "monthlyPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "notificationEmailConfigured": { "type": "boolean" },
          "notificationEnabled": { "type": "boolean" },
          "notificationLocale": { "enum": ["en", "uk"], "type": "string" },
          "overageAmount": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "overageCredits": { "type": "string" },
          "overageLimit": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "overageUnitPrice": {
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "paymentState": {
            "description": "Payment state; unknown cannot be retried as a new payment.",
            "type": "string"
          },
          "periodEnd": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "periodStart": {
            "anyOf": [
              { "format": "date-time", "type": "string" },
              { "type": "null" }
            ]
          },
          "planId": { "type": "string" },
          "planName": { "type": "string" },
          "remainingCredits": { "type": "string" },
          "status": {
            "enum": ["pending_payment", "active", "past_due", "cancelled"],
            "type": "string"
          },
          "unit": { "type": "string" },
          "usedCredits": { "type": "string" }
        },
        "required": [
          "id",
          "planId",
          "customerRef",
          "status",
          "planName",
          "unit",
          "currency",
          "monthlyPrice",
          "includedCredits",
          "overageUnitPrice",
          "overageLimit",
          "periodStart",
          "periodEnd",
          "usedCredits",
          "remainingCredits",
          "overageCredits",
          "overageAmount",
          "cancelAtPeriodEnd",
          "autoRenewEnabled",
          "paymentState",
          "notificationEnabled",
          "notificationEmailConfigured",
          "notificationLocale",
          "createdAt"
        ],
        "type": "object"
      },
      "ValidationErrorResponseDto": {
        "properties": {
          "error": { "example": "Bad Request", "type": "string" },
          "message": {
            "example": [
              "amount must be a decimal string in major units, e.g. \"12.30\"; JSON numbers are not accepted for money (got 12.3)"
            ],
            "items": { "type": "string" },
            "type": "array"
          },
          "statusCode": { "example": 400, "type": "number" }
        },
        "required": ["statusCode", "error", "message"],
        "type": "object"
      },
      "WebhookEvent": {
        "description": "Signed merchant event envelope (ADR-005/010). Event id and created_at remain unchanged on retries. Additional fields and event types may be added.",
        "properties": {
          "api_version": {
            "description": "Payload version, fixed for the event (retries and re-drives keep it). Current: 2026-10-31. See the webhook event catalogue.",
            "example": "2026-10-31",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
            "type": "string"
          },
          "created_at": {
            "description": "UTC time when the event was recorded, not delivery time",
            "format": "date-time",
            "type": "string"
          },
          "data": {
            "properties": {
              "paymentData": {
                "description": "Opaque JSON provider data. Shape varies by provider and event; may contain personal data. Do not log it."
              },
              "transaction": { "$ref": "#/components/schemas/TransactionDto" }
            },
            "required": ["transaction", "paymentData"],
            "type": "object"
          },
          "id": {
            "description": "Stable event identifier (TypeID with prefix evt_); identical on every retry and re-drive. Use the signed body id for deduplication",
            "example": "evt_0j7s2pft4v8b9t8nj2cra1eg00",
            "pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$",
            "type": "string"
          },
          "livemode": {
            "description": "Mode of the transaction snapshot; false for sandbox.",
            "type": "boolean"
          },
          "type": {
            "description": "Payment status event type; refund events use RefundWebhookEvent",
            "example": "transaction.updated",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "api_version",
          "created_at",
          "data",
          "livemode"
        ],
        "type": "object"
      },
      "WithdrawalCryptoDestinationDto": {
        "properties": {
          "destinationAddress": {
            "description": "Bitcoin regtest destination for the B2BinPay sandbox only.",
            "pattern": "^bcrt1q[023456789acdefghjklmnpqrstuvwxyz]{38,58}$",
            "type": "string"
          },
          "networkId": { "enum": ["BTC"], "type": "string" }
        },
        "required": ["networkId", "destinationAddress"],
        "type": "object"
      },
      "WithdrawalQuoteDto": {
        "properties": {
          "amount": {
            "example": "25.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "crypto": {
            "$ref": "#/components/schemas/WithdrawalCryptoDestinationDto"
          },
          "currency": { "example": "EUR", "type": "string" },
          "methodChoiceId": { "type": "string" }
        },
        "required": ["methodChoiceId", "amount", "currency"],
        "type": "object"
      },
      "WithdrawalRequestDto": {
        "properties": {
          "amount": {
            "example": "25.00",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "crypto": {
            "$ref": "#/components/schemas/WithdrawalCryptoDestinationDto"
          },
          "currency": { "example": "EUR", "type": "string" },
          "expectedFee": {
            "example": "0.50",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "expectedRevision": {
            "description": "Opaque server quote priceRevision; revalidated before reservation.",
            "type": "string"
          },
          "expectedTotal": {
            "example": "25.50",
            "pattern": "^(0|[1-9]\\d{0,19})(\\.\\d{1,18})?$",
            "type": "string"
          },
          "methodChoiceId": { "type": "string" },
          "quoteId": { "type": "string" }
        },
        "required": [
          "methodChoiceId",
          "amount",
          "currency",
          "expectedRevision",
          "expectedFee",
          "expectedTotal"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "X-API-Key": { "in": "header", "name": "x-api-key", "type": "apiKey" },
      "bearer": {
        "bearerFormat": "Opaque cashier player grant",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": { "name": "OrsunPay" },
    "description": "Server-to-server merchant payments. Money is always a decimal string in major units.",
    "title": "OrsunPay Merchant API",
    "version": "1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/cashier-ui/crypto/invoices": {
      "post": {
        "operationId": "CashierCryptoController_issue",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CryptoIssueDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Create a crypto invoice",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/crypto/invoices/{id}": {
      "get": {
        "operationId": "CashierCryptoController_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Retrieve a crypto invoice",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/crypto/quote": {
      "post": {
        "operationId": "CashierCryptoController_quote",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CryptoQuoteDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Quote a crypto deposit",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/frame-policy/{id}": {
      "get": {
        "operationId": "CashierFrameController_policy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "summary": "Read the stored merchant frame origin; does not authorize a session",
        "tags": ["Cashier embedding policy"]
      }
    },
    "/v1/cashier-ui/methods": {
      "get": {
        "operationId": "CashierUiController_methods",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "List eligible deposit methods",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/operations": {
      "get": {
        "operationId": "CashierUiController_operations",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "List cashier operations",
        "tags": ["Cashier player"]
      },
      "post": {
        "operationId": "CashierUiController_submit",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CashierDepositDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Submit a deposit",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/operations/{id}": {
      "get": {
        "operationId": "CashierUiController_operation",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Retrieve a cashier operation",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/quote": {
      "post": {
        "operationId": "CashierUiController_quote",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CashierQuoteDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashierQuoteResponseDto"
                }
              }
            },
            "description": ""
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Quote a deposit",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/reauthorize": {
      "post": {
        "operationId": "CashierUiController_reauthorize",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Refresh cashier authorization",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/session": {
      "get": {
        "operationId": "CashierUiController_session",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Read the authenticated player cashier and its currency",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/template": {
      "get": {
        "operationId": "CashierUiController_template",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Read the immutable presentation pinned when the player session was created",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals": {
      "get": {
        "operationId": "CashierWithdrawalController_list",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "List withdrawals",
        "tags": ["Cashier player"]
      },
      "post": {
        "operationId": "CashierWithdrawalController_request",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WithdrawalRequestDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Request a withdrawal",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals/choices": {
      "get": {
        "operationId": "CashierWithdrawalController_choices",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "List eligible withdrawal methods",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals/quote": {
      "post": {
        "operationId": "CashierWithdrawalController_quote",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WithdrawalQuoteDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Quote a withdrawal",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals/{id}": {
      "get": {
        "operationId": "CashierWithdrawalController_read",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Retrieve a withdrawal",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals/{id}/cancel": {
      "post": {
        "operationId": "CashierWithdrawalController_cancel",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Cancel a withdrawal",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier-ui/withdrawals/{id}/reconcile-reserve": {
      "post": {
        "operationId": "CashierWithdrawalController_reconcile",
        "parameters": [
          {
            "in": "header",
            "name": "X-Cashier-Instance-Id",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": ""
          }
        },
        "security": [{ "bearer": [] }],
        "summary": "Reconcile a withdrawal reservation",
        "tags": ["Cashier player"]
      }
    },
    "/v1/cashier/sessions": {
      "post": {
        "operationId": "createCashierSession",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CashierCreateSessionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashierGrantResponseDto"
                }
              }
            },
            "description": ""
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": ""
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Authorize a player cashier from the merchant backend",
        "tags": ["Cashier sessions (merchant S2S)"]
      }
    },
    "/v1/cashier/sessions/{id}/access-grants": {
      "post": {
        "operationId": "mintCashierAccessGrant",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CashierMintGrantDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CashierGrantResponseDto"
                }
              }
            },
            "description": ""
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": ""
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Renew player access for the same bound instance",
        "tags": ["Cashier sessions (merchant S2S)"]
      }
    },
    "/v1/cashier/sessions/{id}/revoke": {
      "post": {
        "operationId": "revokeCashierSession",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CashierRevokeSessionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": ""
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Revoke this player cashier immediately",
        "tags": ["Cashier sessions (merchant S2S)"]
      }
    },
    "/v1/cashier/wallet/receipts": {
      "post": {
        "operationId": "CashierWalletReceiptController_receipt",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CashierWalletReceiptDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": { "description": "" },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": ""
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Acknowledge a wallet effect",
        "tags": ["Cashier sessions (merchant S2S)"]
      }
    },
    "/v1/payment": {
      "get": {
        "description": "With orderId returns one transaction or 404. Otherwise returns newest first by created_at and ID; use next_cursor as starting_after. Merchant and live/test mode come only from the API key. All money is decimal-string major units.",
        "operationId": "listPayments",
        "parameters": [
          {
            "description": "Exact merchant order ID; cannot be combined with list parameters",
            "in": "query",
            "name": "orderId",
            "required": false,
            "schema": { "maxLength": 100, "type": "string" }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "type": "number"
            }
          },
          {
            "description": "next_cursor from the previous page (transaction ID)",
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": { "maxLength": 32, "type": "string" }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "CREATED",
                "WAIT_APPROVE",
                "PROCESSING",
                "SUCCESS",
                "DECLINED",
                "CANCELED",
                "EXPIRED"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": { "enum": ["SALE", "PAYOUT"], "type": "string" }
          },
          {
            "description": "Inclusive creation time, with timezone",
            "in": "query",
            "name": "created_gte",
            "required": false,
            "schema": { "format": "date-time", "type": "string" }
          },
          {
            "description": "Exclusive creation time, with timezone",
            "in": "query",
            "name": "created_lt",
            "required": false,
            "schema": { "format": "date-time", "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/PaymentListResponseDto" },
                    {
                      "$ref": "#/components/schemas/TransactionStatusResponseDto"
                    }
                  ]
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponseDto"
                }
              }
            },
            "description": "Invalid query or cursor"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionNotFoundResponseDto"
                }
              }
            },
            "description": "Payment not found for the authenticated merchant and mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core unavailable"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "Authentication temporarily unavailable"
          },
          "504": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core deadline exceeded"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List payments or find by order ID",
        "tags": ["Payments"]
      }
    },
    "/v1/payment-links": {
      "get": {
        "description": "Scoped to the authenticated API key’s live/test mode. Keyset pagination: pass nextCursor from the previous page as cursor; null means the last page.",
        "operationId": "listPaymentLinks",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "type": "number"
            }
          },
          {
            "description": "Opaque nextCursor from the previous response.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "amount": "12.34",
                      "createdAt": "2026-10-11T10:00:00.000Z",
                      "currency": "EUR",
                      "description": "Order payment",
                      "expired": false,
                      "expiresAt": "2026-10-18T10:00:00.000Z",
                      "failureUrl": "https://shop.example.com/failure",
                      "id": "pl_01j9a6d6dqevssvyw7s97pkrga",
                      "isActive": true,
                      "livemode": true,
                      "maxUses": 1,
                      "merchantId": "mer_example",
                      "metadata": { "cartId": "cart_example" },
                      "reusable": false,
                      "slug": "aBcDeFgHiJkLmNoPqRsTuVwX",
                      "status": "ACTIVE",
                      "successUrl": "https://shop.example.com/success",
                      "url": "https://pay.example.com/l/aBcDeFgHiJkLmNoPqRsTuVwX",
                      "usesCount": 0
                    }
                  ],
                  "nextCursor": null
                },
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinksResponseDto"
                }
              }
            },
            "description": "One page of links, newest first",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": "PAYMENT_LINK_INVALID_CURSOR",
                  "errorCode": "PAYMENT_LINK_INVALID_CURSOR",
                  "message": "PAYMENT_LINK_INVALID_CURSOR",
                  "status": false,
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Query validation, PAYMENT_LINK_INVALID_LIMIT or PAYMENT_LINK_INVALID_CURSOR"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_UNAVAILABLE",
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "message": "Payment links are temporarily unavailable",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable"
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; a create may still complete"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List the authenticated merchant’s links, newest first",
        "tags": ["Payment links"]
      },
      "post": {
        "description": "Creates a link in the authenticated API key’s live/test mode that the merchant can share with a buyer. Money is a decimal string in major units within the currency exponent. Idempotency-Key is required: a retry with the same key and body returns the stored answer with Idempotency-Replayed: true.",
        "operationId": "createPaymentLink",
        "parameters": [
          {
            "description": "1–255 printable ASCII characters without spaces. Reuse for retries; replay responses carry Idempotency-Replayed: true.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "example": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentLinkRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "amount": "12.34",
                  "createdAt": "2026-10-11T10:00:00.000Z",
                  "currency": "EUR",
                  "description": "Order payment",
                  "expired": false,
                  "expiresAt": "2026-10-18T10:00:00.000Z",
                  "failureUrl": "https://shop.example.com/failure",
                  "id": "pl_01j9a6d6dqevssvyw7s97pkrga",
                  "isActive": true,
                  "livemode": true,
                  "maxUses": 1,
                  "merchantId": "mer_example",
                  "metadata": { "cartId": "cart_example" },
                  "reusable": false,
                  "slug": "aBcDeFgHiJkLmNoPqRsTuVwX",
                  "status": "ACTIVE",
                  "successUrl": "https://shop.example.com/success",
                  "url": "https://pay.example.com/l/aBcDeFgHiJkLmNoPqRsTuVwX",
                  "usesCount": 0
                },
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            },
            "description": "Link created, or the stored answer for a replayed Idempotency-Key",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "invalidAmount": {
                    "summary": "Amount beyond the currency exponent",
                    "value": {
                      "error": "PAYMENT_LINK_INVALID_AMOUNT",
                      "errorCode": "PAYMENT_LINK_INVALID_AMOUNT",
                      "message": "amount has more decimals than EUR allows",
                      "status": false,
                      "statusCode": 400
                    }
                  },
                  "invalidKey": {
                    "summary": "Missing Idempotency-Key",
                    "value": {
                      "error": "IDEMPOTENCY_KEY_INVALID",
                      "errorCode": "IDEMPOTENCY_KEY_INVALID",
                      "message": "Idempotency-Key is required",
                      "status": false,
                      "statusCode": 400
                    }
                  }
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Body validation, IDEMPOTENCY_KEY_INVALID, or a PAYMENT_LINK_* code: INVALID_AMOUNT, UNSUPPORTED_CURRENCY, INVALID_EXPIRY, INVALID_MAX_USES, REDIRECT_URL_NOT_ALLOWED, METADATA_TOO_LARGE, INVALID_TEXT."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "error": "IDEMPOTENCY_IN_PROGRESS",
                  "errorCode": "IDEMPOTENCY_IN_PROGRESS",
                  "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                  "message": "A request with this Idempotency-Key is still being processed; retry later",
                  "status": false,
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "IDEMPOTENCY_IN_PROGRESS; retry with the same key after Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying with the same key",
                "schema": { "example": "1", "type": "string" }
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "error": "IDEMPOTENCY_KEY_REUSED",
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                  "message": "Idempotency-Key was already used with a different request; use a new key for a new request",
                  "status": false,
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED with another body or endpoint."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_UNAVAILABLE",
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "message": "Payment links are temporarily unavailable",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable"
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; a create may still complete"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Create a merchant-scoped payment link",
        "tags": ["Payment links"]
      }
    },
    "/v1/payment-links/{id}": {
      "get": {
        "description": "Links of other merchants or API-key modes answer 404 PAYMENT_LINK_NOT_FOUND, like unknown ids.",
        "operationId": "getPaymentLink",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "amount": "12.34",
                  "createdAt": "2026-10-11T10:00:00.000Z",
                  "currency": "EUR",
                  "description": "Order payment",
                  "expired": false,
                  "expiresAt": "2026-10-18T10:00:00.000Z",
                  "failureUrl": "https://shop.example.com/failure",
                  "id": "pl_01j9a6d6dqevssvyw7s97pkrga",
                  "isActive": true,
                  "livemode": true,
                  "maxUses": 1,
                  "merchantId": "mer_example",
                  "metadata": { "cartId": "cart_example" },
                  "reusable": false,
                  "slug": "aBcDeFgHiJkLmNoPqRsTuVwX",
                  "status": "ACTIVE",
                  "successUrl": "https://shop.example.com/success",
                  "url": "https://pay.example.com/l/aBcDeFgHiJkLmNoPqRsTuVwX",
                  "usesCount": 0
                },
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            },
            "description": "The link",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "PAYMENT_LINK_NOT_FOUND",
                  "errorCode": "PAYMENT_LINK_NOT_FOUND",
                  "message": "PAYMENT_LINK_NOT_FOUND",
                  "status": false,
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "PAYMENT_LINK_NOT_FOUND: unknown link or a link of another merchant/API-key mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_UNAVAILABLE",
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "message": "Payment links are temporarily unavailable",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable"
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; a create may still complete"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Get a link owned by the authenticated merchant",
        "tags": ["Payment links"]
      }
    },
    "/v1/payment-links/{id}/deactivate": {
      "post": {
        "description": "Only links in the authenticated API key’s live/test mode are accessible. A deactivated link cannot be reopened. Deactivating an inactive link returns it unchanged.",
        "operationId": "deactivatePaymentLink",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "amount": "12.34",
                  "createdAt": "2026-10-11T10:00:00.000Z",
                  "currency": "EUR",
                  "description": "Order payment",
                  "expired": false,
                  "expiresAt": "2026-10-18T10:00:00.000Z",
                  "failureUrl": "https://shop.example.com/failure",
                  "id": "pl_01j9a6d6dqevssvyw7s97pkrga",
                  "isActive": false,
                  "livemode": true,
                  "maxUses": 1,
                  "merchantId": "mer_example",
                  "metadata": { "cartId": "cart_example" },
                  "reusable": false,
                  "slug": "aBcDeFgHiJkLmNoPqRsTuVwX",
                  "status": "INACTIVE",
                  "successUrl": "https://shop.example.com/success",
                  "url": "https://pay.example.com/l/aBcDeFgHiJkLmNoPqRsTuVwX",
                  "usesCount": 0
                },
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResponseDto"
                }
              }
            },
            "description": "The link, now inactive",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "PAYMENT_LINK_NOT_FOUND",
                  "errorCode": "PAYMENT_LINK_NOT_FOUND",
                  "message": "PAYMENT_LINK_NOT_FOUND",
                  "status": false,
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "PAYMENT_LINK_NOT_FOUND: unknown link or a link of another merchant/API-key mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_UNAVAILABLE",
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "message": "Payment links are temporarily unavailable",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable"
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; a create may still complete"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Permanently deactivate a link; repeated requests are safe",
        "tags": ["Payment links"]
      }
    },
    "/v1/payment/payout": {
      "post": {
        "description": "Creates a payout through an eligible provider connection. Use the payment method configured for the merchant, mode, currency and payout rail. Colibrix card payouts require sourceTransactionId from an eligible earlier sale. Bank payouts require a supported connection and its beneficiary fields. Money is a decimal string in major units (`\"amount\": \"10.00\"`), in the request and in the response.",
        "operationId": "createPayout",
        "parameters": [
          {
            "description": "Optional, recommended. 1-255 printable ASCII characters without spaces (e.g. a UUID v4) generated once per payment attempt and reused for every retry of it. Scoped to the merchant, kept 24 h. A retry of a finished request returns the stored status and body with `Idempotency-Replayed: true`; a retry while the first request is still running gets 409 IDEMPOTENCY_IN_PROGRESS with `Retry-After`; the same key with a different body or endpoint gets 422 IDEMPOTENCY_KEY_REUSED.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "example": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "full": {
                  "summary": "With method, customer and merchant metadata",
                  "value": {
                    "amount": "12.30",
                    "buyerId": "buyer_example",
                    "callbackUrl": "https://shop.example.com/webhooks/orsunpay",
                    "currency": "EUR",
                    "customer": {
                      "country": "US",
                      "email": "buyer@example.com",
                      "firstName": "Jane",
                      "lastName": "Doe"
                    },
                    "failureUrl": "https://shop.example.com/failure",
                    "locale": "en-US",
                    "merchantId": "mr_example",
                    "metadata": { "cartId": "cart_example" },
                    "orderId": "order_example_001",
                    "paymentMethod": "cr_example",
                    "paymentMethodInput": {},
                    "returnUrl": "https://shop.example.com/return",
                    "successUrl": "https://shop.example.com/success"
                  }
                },
                "minimal": {
                  "summary": "Minimum required fields",
                  "value": {
                    "amount": "12.30",
                    "buyerId": "buyer_example",
                    "callbackUrl": "https://shop.example.com/webhooks/orsunpay",
                    "currency": "EUR",
                    "failureUrl": "https://shop.example.com/failure",
                    "merchantId": "mr_example",
                    "orderId": "order_example_001",
                    "paymentMethod": "cr_example",
                    "returnUrl": "https://shop.example.com/return",
                    "successUrl": "https://shop.example.com/success"
                  }
                }
              },
              "schema": { "$ref": "#/components/schemas/PayoutRequestDto" }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "businessError": {
                    "summary": "Rejected by the payment core",
                    "value": {
                      "error": "INVALID_AMOUNT: amount 12.345 has more than 2 decimal places allowed for EUR",
                      "status": false
                    }
                  },
                  "livemodeMismatch": {
                    "summary": "Payment declined before PSP dispatch because the credential mode differs",
                    "value": {
                      "status": true,
                      "transaction": {
                        "action": "PAYOUT",
                        "amount": "10.00",
                        "buyerId": "buyer_001",
                        "callbackUrl": "https://merchant.com/callback",
                        "companyId": "co_123",
                        "createdAt": "2025-08-27T08:49:34.336Z",
                        "credentialConfigId": "cr_hvntdai7ag38j8dmlbiunyga",
                        "currency": "EUR",
                        "currencyRate": null,
                        "customerId": "cu_a76ew9iilsw46mtvmif6tits",
                        "errorCode": "LIVEMODE_MISMATCH",
                        "failureUrl": "https://merchant.com/failure",
                        "feeAmount": "10",
                        "feeCharge": "PERCENTAGE",
                        "feeRoundingRemainder": "0",
                        "feeType": "TOP",
                        "finalStatusUpdatedAt": null,
                        "fxRoundingRemainder": null,
                        "id": "tr_xv0p2q5scocndpejk0nud75q",
                        "isFeeEnabled": true,
                        "livemode": true,
                        "locale": "en-US",
                        "merchantId": "mr_hkvats9n1pmbznf1j6yu8bry",
                        "metadata": {
                          "cartId": "cart_123",
                          "promoCode": "SUMMER24"
                        },
                        "orderId": "order_20240612_001",
                        "paymentMethod": "mbway",
                        "processingAmount": "10.00",
                        "processingAmountWithFee": "11.00",
                        "processingCurrency": "EUR",
                        "processingFeeAmount": "1.00",
                        "provider": "adyen",
                        "pspTransactionId": null,
                        "returnUrl": "https://merchant.com/return",
                        "ruleId": null,
                        "status": "DECLINED",
                        "successUrl": "https://merchant.com/success",
                        "updatedAt": "2025-08-27T08:49:34.336Z"
                      }
                    }
                  },
                  "success": {
                    "summary": "Successful withdrawal creation",
                    "value": {
                      "status": true,
                      "transaction": {
                        "action": "PAYOUT",
                        "amount": "10.00",
                        "buyerId": "buyer_001",
                        "callbackUrl": "https://merchant.com/callback",
                        "companyId": "co_123",
                        "createdAt": "2025-08-27T08:49:34.336Z",
                        "credentialConfigId": "cr_hvntdai7ag38j8dmlbiunyga",
                        "currency": "EUR",
                        "currencyRate": null,
                        "customerId": "cu_a76ew9iilsw46mtvmif6tits",
                        "errorCode": null,
                        "failureUrl": "https://merchant.com/failure",
                        "feeAmount": "10",
                        "feeCharge": "PERCENTAGE",
                        "feeRoundingRemainder": "0",
                        "feeType": "TOP",
                        "finalStatusUpdatedAt": null,
                        "fxRoundingRemainder": null,
                        "id": "tr_xv0p2q5scocndpejk0nud75q",
                        "isFeeEnabled": true,
                        "livemode": true,
                        "locale": "en-US",
                        "merchantId": "mr_hkvats9n1pmbznf1j6yu8bry",
                        "metadata": {
                          "cartId": "cart_123",
                          "promoCode": "SUMMER24"
                        },
                        "orderId": "order_20240612_001",
                        "paymentMethod": "mbway",
                        "processingAmount": "10.00",
                        "processingAmountWithFee": "11.00",
                        "processingCurrency": "EUR",
                        "processingFeeAmount": "1.00",
                        "provider": "adyen",
                        "pspTransactionId": null,
                        "returnUrl": "https://merchant.com/return",
                        "ruleId": null,
                        "status": "CREATED",
                        "successUrl": "https://merchant.com/success",
                        "updatedAt": "2025-08-27T08:49:34.336Z"
                      }
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/PaymentResponseDto" }
              }
            },
            "description": "Transaction created, or `status: false` with a business `error` (e.g. `INVALID_AMOUNT: ...` when the amount has more decimals than the currency allows). Money fields are decimal strings in major units. LIVEMODE_MISMATCH is a declined transaction returned with status: true, not an HTTP error; no PSP operation is sent.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present (`true`) when the body is a replay of an earlier request with the same Idempotency-Key",
                "schema": { "enum": ["true"], "type": "string" }
              },
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "amountAsNumber": {
                    "summary": "amount sent as a JSON number",
                    "value": {
                      "error": "Bad Request",
                      "message": [
                        "amount must be a decimal string in major units, e.g. \"12.30\"; JSON numbers are not accepted for money (got 12.3)"
                      ],
                      "statusCode": 400
                    }
                  },
                  "invalidKey": {
                    "summary": "Invalid Idempotency-Key",
                    "value": {
                      "error": "IDEMPOTENCY_KEY_INVALID",
                      "errorCode": "IDEMPOTENCY_KEY_INVALID",
                      "message": "Idempotency-Key must be a single value of 1-255 printable ASCII characters without spaces",
                      "status": false,
                      "statusCode": 400
                    }
                  },
                  "noCredentialsForMode": {
                    "summary": "No usable credentials in the authenticated API key mode",
                    "value": {
                      "error": "NO_CREDENTIALS_FOR_MODE",
                      "errorCode": "NO_CREDENTIALS_FOR_MODE",
                      "message": "No credentials are available for this payment mode",
                      "status": false,
                      "statusCode": 400
                    }
                  }
                },
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "Invalid request: body validation (e.g. `amount` sent as a JSON number) or an invalid `Idempotency-Key` (IDEMPOTENCY_KEY_INVALID), NO_CREDENTIALS_FOR_MODE (no usable credential in the key mode)."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Invalid API key"
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "duplicateOrder": {
                    "summary": "Duplicate orderId",
                    "value": {
                      "error": "DUPLICATE_ORDER_ID",
                      "errorCode": "DUPLICATE_ORDER_ID",
                      "existingTransactionId": "tr_x8k2p0q5scocndpejk0nud75q",
                      "message": "A transaction with orderId \"A-1001\" already exists for this merchant",
                      "orderId": "A-1001",
                      "status": false,
                      "statusCode": 409
                    }
                  },
                  "inProgress": {
                    "summary": "Same Idempotency-Key still in progress",
                    "value": {
                      "error": "IDEMPOTENCY_IN_PROGRESS",
                      "errorCode": "IDEMPOTENCY_IN_PROGRESS",
                      "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                      "message": "A request with this Idempotency-Key is still being processed; retry later",
                      "status": false,
                      "statusCode": 409
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "DUPLICATE_ORDER_ID: the merchant already has a transaction with this `orderId` (see `existingTransactionId`); or IDEMPOTENCY_IN_PROGRESS: a request with the same Idempotency-Key is still running, retry after `Retry-After` seconds with the same key.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present when this 409 is a replay of an earlier answer for the same key",
                "schema": { "enum": ["true"], "type": "string" }
              },
              "Retry-After": {
                "description": "IDEMPOTENCY_IN_PROGRESS only: seconds to wait before retrying",
                "schema": { "example": "1", "type": "string" }
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "reusedKey": {
                    "value": {
                      "error": "IDEMPOTENCY_KEY_REUSED",
                      "errorCode": "IDEMPOTENCY_KEY_REUSED",
                      "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                      "message": "Idempotency-Key was already used with a different request; use a new key for a new request",
                      "status": false,
                      "statusCode": 422
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED: the Idempotency-Key was already used with a different request; ORDER_ID_RESERVED: the pl_ orderId prefix is reserved for payment links"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_ERROR",
                  "errorCode": "UPSTREAM_ERROR",
                  "message": "The payment core failed to process the request; retry with the same Idempotency-Key",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable. Retry with the same Idempotency-Key."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later with the same request"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time; the operation may still complete. Retry with the same Idempotency-Key to get its result",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; the operation may still complete. Retry with the same Idempotency-Key to get its result."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Create withdrawal transaction (Payout)",
        "tags": ["Payments"]
      }
    },
    "/v1/payment/sale": {
      "post": {
        "description": "Creates a new deposit transaction for customer account funding. Supports various payment methods including cryptocurrencies, e-wallets, and BNPL services. Money is a decimal string in major units (`\"amount\": \"10.00\"`), in the request and in the response. Without `paymentMethod`, or with incomplete `paymentMethodInput`, the response carries `paymentPageUrl`: the hosted payment page where the buyer picks a method and types the missing details.",
        "operationId": "createSale",
        "parameters": [
          {
            "description": "Optional, recommended. 1-255 printable ASCII characters without spaces (e.g. a UUID v4) generated once per payment attempt and reused for every retry of it. Scoped to the merchant, kept 24 h. A retry of a finished request returns the stored status and body with `Idempotency-Replayed: true`; a retry while the first request is still running gets 409 IDEMPOTENCY_IN_PROGRESS with `Retry-After`; the same key with a different body or endpoint gets 422 IDEMPOTENCY_KEY_REUSED.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "example": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "full": {
                  "summary": "With method, customer and merchant metadata",
                  "value": {
                    "amount": "12.30",
                    "buyerId": "buyer_example",
                    "callbackUrl": "https://shop.example.com/webhooks/orsunpay",
                    "currency": "EUR",
                    "customer": {
                      "country": "US",
                      "email": "buyer@example.com",
                      "firstName": "Jane",
                      "lastName": "Doe"
                    },
                    "description": "Coffee beans",
                    "failureUrl": "https://shop.example.com/failure",
                    "locale": "en-US",
                    "merchantId": "mr_example",
                    "metadata": { "cartId": "cart_example" },
                    "orderId": "order_example_001",
                    "paymentMethod": "cr_example",
                    "paymentMethodInput": {},
                    "returnUrl": "https://shop.example.com/return",
                    "successUrl": "https://shop.example.com/success"
                  }
                },
                "minimal": {
                  "summary": "Minimum required fields",
                  "value": {
                    "amount": "12.30",
                    "buyerId": "buyer_example",
                    "callbackUrl": "https://shop.example.com/webhooks/orsunpay",
                    "currency": "EUR",
                    "failureUrl": "https://shop.example.com/failure",
                    "merchantId": "mr_example",
                    "orderId": "order_example_001",
                    "returnUrl": "https://shop.example.com/return",
                    "successUrl": "https://shop.example.com/success"
                  }
                }
              },
              "schema": { "$ref": "#/components/schemas/SaleRequestDto" }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "examples": {
                  "businessError": {
                    "summary": "Rejected by the payment core",
                    "value": {
                      "error": "INVALID_AMOUNT: amount 12.345 has more than 2 decimal places allowed for EUR",
                      "status": false
                    }
                  },
                  "livemodeMismatch": {
                    "summary": "Payment declined before PSP dispatch because the credential mode differs",
                    "value": {
                      "status": true,
                      "transaction": {
                        "action": "SALE",
                        "amount": "10.00",
                        "buyerId": "buyer_001",
                        "callbackUrl": "https://merchant.com/callback",
                        "companyId": "co_123",
                        "createdAt": "2025-08-27T08:49:34.336Z",
                        "credentialConfigId": "cr_hvntdai7ag38j8dmlbiunyga",
                        "currency": "EUR",
                        "currencyRate": null,
                        "customerId": "cu_a76ew9iilsw46mtvmif6tits",
                        "errorCode": "LIVEMODE_MISMATCH",
                        "failureUrl": "https://merchant.com/failure",
                        "feeAmount": "10",
                        "feeCharge": "PERCENTAGE",
                        "feeRoundingRemainder": "0",
                        "feeType": "TOP",
                        "finalStatusUpdatedAt": null,
                        "fxRoundingRemainder": null,
                        "id": "tr_xv0p2q5scocndpejk0nud75q",
                        "isFeeEnabled": true,
                        "livemode": true,
                        "locale": "en-US",
                        "merchantId": "mr_hkvats9n1pmbznf1j6yu8bry",
                        "metadata": {
                          "cartId": "cart_123",
                          "promoCode": "SUMMER24"
                        },
                        "orderId": "order_20240612_001",
                        "paymentMethod": "mbway",
                        "processingAmount": "10.00",
                        "processingAmountWithFee": "11.00",
                        "processingCurrency": "EUR",
                        "processingFeeAmount": "1.00",
                        "provider": "adyen",
                        "pspTransactionId": null,
                        "returnUrl": "https://merchant.com/return",
                        "ruleId": null,
                        "status": "DECLINED",
                        "successUrl": "https://merchant.com/success",
                        "updatedAt": "2025-08-27T08:49:34.336Z"
                      }
                    }
                  },
                  "success": {
                    "summary": "Successful deposit creation",
                    "value": {
                      "status": true,
                      "transaction": {
                        "action": "SALE",
                        "amount": "10.00",
                        "buyerId": "buyer_001",
                        "callbackUrl": "https://merchant.com/callback",
                        "companyId": "co_123",
                        "createdAt": "2025-08-27T08:49:34.336Z",
                        "credentialConfigId": "cr_hvntdai7ag38j8dmlbiunyga",
                        "currency": "EUR",
                        "currencyRate": null,
                        "customerId": "cu_a76ew9iilsw46mtvmif6tits",
                        "errorCode": null,
                        "failureUrl": "https://merchant.com/failure",
                        "feeAmount": "10",
                        "feeCharge": "PERCENTAGE",
                        "feeRoundingRemainder": "0",
                        "feeType": "TOP",
                        "finalStatusUpdatedAt": null,
                        "fxRoundingRemainder": null,
                        "id": "tr_xv0p2q5scocndpejk0nud75q",
                        "isFeeEnabled": true,
                        "livemode": true,
                        "locale": "en-US",
                        "merchantId": "mr_hkvats9n1pmbznf1j6yu8bry",
                        "metadata": {
                          "cartId": "cart_123",
                          "promoCode": "SUMMER24"
                        },
                        "orderId": "order_20240612_001",
                        "paymentMethod": "mbway",
                        "processingAmount": "10.00",
                        "processingAmountWithFee": "11.00",
                        "processingCurrency": "EUR",
                        "processingFeeAmount": "1.00",
                        "provider": "adyen",
                        "pspTransactionId": null,
                        "returnUrl": "https://merchant.com/return",
                        "ruleId": null,
                        "status": "CREATED",
                        "successUrl": "https://merchant.com/success",
                        "updatedAt": "2025-08-27T08:49:34.336Z"
                      },
                      "url": "https://payment-provider.com/pay/abc123"
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/PaymentResponseDto" }
              }
            },
            "description": "Transaction created, or `status: false` with a business `error` (e.g. `INVALID_AMOUNT: ...` when the amount has more decimals than the currency allows). Money fields are decimal strings in major units. LIVEMODE_MISMATCH is a declined transaction returned with status: true, not an HTTP error; no PSP operation is sent.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present (`true`) when the body is a replay of an earlier request with the same Idempotency-Key",
                "schema": { "enum": ["true"], "type": "string" }
              },
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "examples": {
                  "amountAsNumber": {
                    "summary": "amount sent as a JSON number",
                    "value": {
                      "error": "Bad Request",
                      "message": [
                        "amount must be a decimal string in major units, e.g. \"12.30\"; JSON numbers are not accepted for money (got 12.3)"
                      ],
                      "statusCode": 400
                    }
                  },
                  "invalidKey": {
                    "summary": "Invalid Idempotency-Key",
                    "value": {
                      "error": "IDEMPOTENCY_KEY_INVALID",
                      "errorCode": "IDEMPOTENCY_KEY_INVALID",
                      "message": "Idempotency-Key must be a single value of 1-255 printable ASCII characters without spaces",
                      "status": false,
                      "statusCode": 400
                    }
                  },
                  "noCredentialsForMode": {
                    "summary": "No usable credentials in the authenticated API key mode",
                    "value": {
                      "error": "NO_CREDENTIALS_FOR_MODE",
                      "errorCode": "NO_CREDENTIALS_FOR_MODE",
                      "message": "No credentials are available for this payment mode",
                      "status": false,
                      "statusCode": 400
                    }
                  }
                },
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "Invalid request: body validation (e.g. `amount` sent as a JSON number) or an invalid `Idempotency-Key` (IDEMPOTENCY_KEY_INVALID), NO_CREDENTIALS_FOR_MODE (no usable credential in the key mode)."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Invalid API key"
          },
          "409": {
            "content": {
              "application/json": {
                "examples": {
                  "duplicateOrder": {
                    "summary": "Duplicate orderId",
                    "value": {
                      "error": "DUPLICATE_ORDER_ID",
                      "errorCode": "DUPLICATE_ORDER_ID",
                      "existingTransactionId": "tr_x8k2p0q5scocndpejk0nud75q",
                      "message": "A transaction with orderId \"A-1001\" already exists for this merchant",
                      "orderId": "A-1001",
                      "status": false,
                      "statusCode": 409
                    }
                  },
                  "inProgress": {
                    "summary": "Same Idempotency-Key still in progress",
                    "value": {
                      "error": "IDEMPOTENCY_IN_PROGRESS",
                      "errorCode": "IDEMPOTENCY_IN_PROGRESS",
                      "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                      "message": "A request with this Idempotency-Key is still being processed; retry later",
                      "status": false,
                      "statusCode": 409
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "DUPLICATE_ORDER_ID: the merchant already has a transaction with this `orderId` (see `existingTransactionId`); or IDEMPOTENCY_IN_PROGRESS: a request with the same Idempotency-Key is still running, retry after `Retry-After` seconds with the same key.",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present when this 409 is a replay of an earlier answer for the same key",
                "schema": { "enum": ["true"], "type": "string" }
              },
              "Retry-After": {
                "description": "IDEMPOTENCY_IN_PROGRESS only: seconds to wait before retrying",
                "schema": { "example": "1", "type": "string" }
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "examples": {
                  "customerContact": {
                    "value": {
                      "error": "CUSTOMER_CONTACT_REQUIRED",
                      "errorCode": "CUSTOMER_CONTACT_REQUIRED",
                      "fields": ["customer.email", "customer.country"],
                      "message": "The selected payment method requires valid customer contact details",
                      "status": false,
                      "statusCode": 422
                    }
                  },
                  "reusedKey": {
                    "value": {
                      "error": "IDEMPOTENCY_KEY_REUSED",
                      "errorCode": "IDEMPOTENCY_KEY_REUSED",
                      "idempotencyKey": "0b6f2c1e-4c7a-4a43-9a51-6a4b1d7e9f10",
                      "message": "Idempotency-Key was already used with a different request; use a new key for a new request",
                      "status": false,
                      "statusCode": 422
                    }
                  }
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED: the Idempotency-Key was already used with a different request; ORDER_ID_RESERVED: the pl_ orderId prefix is reserved for payment links; CUSTOMER_CONTACT_REQUIRED: the selected Adyen/Brite method requires valid customer contact fields before creation"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_ERROR",
                  "errorCode": "UPSTREAM_ERROR",
                  "message": "The payment core failed to process the request; retry with the same Idempotency-Key",
                  "status": false,
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_ERROR / UPSTREAM_UNAVAILABLE: the payment core failed or is unreachable. Retry with the same Idempotency-Key."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later with the same request"
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "error": "UPSTREAM_TIMEOUT",
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "message": "The payment core did not answer in time; the operation may still complete. Retry with the same Idempotency-Key to get its result",
                  "status": false,
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: no answer in time; the operation may still complete. Retry with the same Idempotency-Key to get its result."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Create deposit transaction (Sale)",
        "tags": ["Payments"]
      }
    },
    "/v1/payment/{id}": {
      "get": {
        "description": "Stored status only; never creates or retries a PSP operation. Same response as GET /v1/transactions/:id.",
        "operationId": "getPaymentById",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionStatusResponseDto"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponseDto"
                }
              }
            },
            "description": "Invalid query or cursor"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionNotFoundResponseDto"
                }
              }
            },
            "description": "Payment not found for the authenticated merchant and mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core unavailable"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "Authentication temporarily unavailable"
          },
          "504": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core deadline exceeded"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Get a payment by ID",
        "tags": ["Payments"]
      }
    },
    "/v1/payment/{id}/refunds": {
      "get": {
        "description": "Read stored refunds for the authenticated merchant and API-key mode. Ordered by refund ID ascending, with at most 100 records per page. Pass nextCursor to continue; null means the final page.",
        "operationId": "listPaymentRefunds",
        "parameters": [
          {
            "description": "Payment transaction ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "maxLength": 32,
              "pattern": "^[A-Za-z0-9_-]{1,32}$",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 100,
              "minimum": 1,
              "type": "number"
            }
          },
          {
            "description": "nextCursor from the preceding page; results are ordered by refund ID ascending.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "maxLength": 32,
              "pattern": "^[A-Za-z0-9_-]{1,32}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "amount": "10.00",
                      "createdAt": "2026-10-11T12:00:00.000Z",
                      "currency": "EUR",
                      "errorCode": null,
                      "id": "rf_example",
                      "metadata": { "orderReference": "order_example" },
                      "providerRefundId": null,
                      "reason": "requested_by_customer",
                      "status": "PENDING",
                      "transactionId": "tr_example",
                      "updatedAt": "2026-10-11T12:00:00.000Z"
                    }
                  ],
                  "nextCursor": null
                },
                "schema": { "$ref": "#/components/schemas/RefundsResponseDto" }
              }
            },
            "description": "Stored refunds ordered by ID ascending"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Bad Request",
                  "message": ["Invalid refund input"],
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "Invalid request, metadata or Idempotency-Key"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing, invalid, expired or inactive merchant API key"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "REFUND_NOT_FOUND",
                  "errorCode": "REFUND_NOT_FOUND",
                  "message": "REFUND_NOT_FOUND",
                  "status": false,
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "REFUND_NOT_FOUND: unknown payment/refund or one belonging to another merchant or API-key mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "authentication": {
                    "value": {
                      "error": "Service Unavailable",
                      "message": "API_KEY_VALIDATION_UNAVAILABLE",
                      "statusCode": 503
                    }
                  },
                  "refund": {
                    "value": {
                      "error": "REFUND_SERVICE_UNAVAILABLE",
                      "errorCode": "REFUND_SERVICE_UNAVAILABLE",
                      "message": "REFUND_SERVICE_UNAVAILABLE",
                      "status": false,
                      "statusCode": 503
                    }
                  }
                },
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "API-key validation or refund core is unavailable. A create may have committed; retry with the same Idempotency-Key."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List refunds for a payment",
        "tags": ["Refunds"]
      },
      "post": {
        "description": "Accepts an asynchronous refund in the authenticated merchant and API-key mode. Omit amount to refund the remaining refundable amount. PENDING/PROCESSING are not completion. The original connection must support refunds and payment and processing currencies must match. Idempotency-Key is mandatory.",
        "operationId": "createRefund",
        "parameters": [
          {
            "description": "Payment transaction ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "maxLength": 32,
              "pattern": "^[A-Za-z0-9_-]{1,32}$",
              "type": "string"
            }
          },
          {
            "description": "A single 1–255 character printable ASCII value without spaces. The checkout-submit: prefix is reserved (case-insensitive). Reuse the same key and body after an uncertain response.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "example": "refund-order-example-1",
              "maxLength": 255,
              "minLength": 1,
              "pattern": "^[\\x21-\\x7e]+$",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "partial": {
                  "summary": "Partial refund",
                  "value": {
                    "amount": "10.00",
                    "metadata": { "orderReference": "order_example" },
                    "reason": "requested_by_customer"
                  }
                },
                "remaining": {
                  "summary": "Refund the remaining amount",
                  "value": {}
                }
              },
              "schema": { "$ref": "#/components/schemas/CreateRefundDto" }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "10.00",
                    "createdAt": "2026-10-11T12:00:00.000Z",
                    "currency": "EUR",
                    "errorCode": null,
                    "id": "rf_example",
                    "metadata": { "orderReference": "order_example" },
                    "providerRefundId": null,
                    "reason": "requested_by_customer",
                    "status": "PENDING",
                    "transactionId": "tr_example",
                    "updatedAt": "2026-10-11T12:00:00.000Z"
                  }
                },
                "schema": { "$ref": "#/components/schemas/RefundResponseDto" }
              }
            },
            "description": "Refund accepted for asynchronous execution",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Returned when the response is an idempotent replay",
                "schema": { "enum": ["true"], "type": "string" }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Bad Request",
                  "message": ["Invalid refund input"],
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "Invalid request, metadata or Idempotency-Key"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing, invalid, expired or inactive merchant API key"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "REFUND_NOT_FOUND",
                  "errorCode": "REFUND_NOT_FOUND",
                  "message": "REFUND_NOT_FOUND",
                  "status": false,
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "REFUND_NOT_FOUND: unknown payment/refund or one belonging to another merchant or API-key mode"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "error": "REFUND_EXCEEDS_AMOUNT",
                  "errorCode": "REFUND_EXCEEDS_AMOUNT",
                  "message": "REFUND_EXCEEDS_AMOUNT",
                  "status": false,
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "REFUND_EXCEEDS_AMOUNT, TRANSACTION_NOT_REFUNDABLE or IDEMPOTENCY_IN_PROGRESS. Currency conversion refunds are unsupported; payment and processing currencies must match.",
            "headers": {
              "Retry-After": {
                "description": "Seconds before retrying the same in-progress request",
                "schema": { "type": "string" }
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "error": "REFUND_NOT_SUPPORTED",
                  "errorCode": "REFUND_NOT_SUPPORTED",
                  "message": "REFUND_NOT_SUPPORTED",
                  "status": false,
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "REFUND_NOT_SUPPORTED (supported providers: Stripe, Mollie, Revolut and Viva), or IDEMPOTENCY_KEY_REUSED with different request input."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "authentication": {
                    "value": {
                      "error": "Service Unavailable",
                      "message": "API_KEY_VALIDATION_UNAVAILABLE",
                      "statusCode": 503
                    }
                  },
                  "refund": {
                    "value": {
                      "error": "REFUND_SERVICE_UNAVAILABLE",
                      "errorCode": "REFUND_SERVICE_UNAVAILABLE",
                      "message": "REFUND_SERVICE_UNAVAILABLE",
                      "status": false,
                      "statusCode": 503
                    }
                  }
                },
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "API-key validation or refund core is unavailable. A create may have committed; retry with the same Idempotency-Key."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Request a full or partial refund",
        "tags": ["Refunds"]
      }
    },
    "/v1/refunds/{id}": {
      "get": {
        "description": "Read the stored refund status in the authenticated merchant and API-key mode. Unknown and foreign refund IDs return the same 404.",
        "operationId": "getRefund",
        "parameters": [
          {
            "description": "Refund ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "maxLength": 32,
              "pattern": "^[A-Za-z0-9_-]{1,32}$",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "10.00",
                    "createdAt": "2026-10-11T12:00:00.000Z",
                    "currency": "EUR",
                    "errorCode": null,
                    "id": "rf_example",
                    "metadata": { "orderReference": "order_example" },
                    "providerRefundId": null,
                    "reason": "requested_by_customer",
                    "status": "PENDING",
                    "transactionId": "tr_example",
                    "updatedAt": "2026-10-11T12:00:00.000Z"
                  }
                },
                "schema": { "$ref": "#/components/schemas/RefundResponseDto" }
              }
            },
            "description": "Stored refund"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Bad Request",
                  "message": ["Invalid refund input"],
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "Invalid request, metadata or Idempotency-Key"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing, invalid, expired or inactive merchant API key"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": "REFUND_NOT_FOUND",
                  "errorCode": "REFUND_NOT_FOUND",
                  "message": "REFUND_NOT_FOUND",
                  "status": false,
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "REFUND_NOT_FOUND: unknown payment/refund or one belonging to another merchant or API-key mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "503": {
            "content": {
              "application/json": {
                "examples": {
                  "authentication": {
                    "value": {
                      "error": "Service Unavailable",
                      "message": "API_KEY_VALIDATION_UNAVAILABLE",
                      "statusCode": 503
                    }
                  },
                  "refund": {
                    "value": {
                      "error": "REFUND_SERVICE_UNAVAILABLE",
                      "errorCode": "REFUND_SERVICE_UNAVAILABLE",
                      "message": "REFUND_SERVICE_UNAVAILABLE",
                      "status": false,
                      "statusCode": 503
                    }
                  }
                },
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                    },
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" }
                  ]
                }
              }
            },
            "description": "API-key validation or refund core is unavailable. A create may have committed; retry with the same Idempotency-Key."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Get a refund",
        "tags": ["Refunds"]
      }
    },
    "/v1/transactions/{id}": {
      "get": {
        "description": "Read the current stored status. Scoped to the merchant and live/test mode of the authenticated API key. IDs longer than 32 characters return 404 without a transaction lookup. No PSP sale is sent. Amounts are decimal strings. Poll after PSP_OUTCOME_UNKNOWN; do not create a second order.",
        "operationId": "getPayment",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "transaction": {
                    "action": "SALE",
                    "amount": "12.30",
                    "createdAt": "2026-10-11T10:00:00.000Z",
                    "currency": "EUR",
                    "errorCode": "PSP_OUTCOME_UNKNOWN",
                    "id": "tr_example",
                    "livemode": true,
                    "orderId": "order_example_001",
                    "processingAmount": "12.30",
                    "processingCurrency": "EUR",
                    "status": "PROCESSING"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/TransactionStatusResponseDto"
                }
              }
            },
            "description": "Current merchant-scoped transaction status",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid API key"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionNotFoundResponseDto"
                }
              }
            },
            "description": "Transaction not found for this merchant and API-key mode"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core failed or unavailable"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation is temporarily unavailable; retry later"
          },
          "504": {
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "Payment core deadline exceeded"
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Poll a merchant transaction",
        "tags": ["Transactions"]
      }
    },
    "/v1/usage-billing/events": {
      "post": {
        "description": "Record positive credits with at most six fractional digits at server receipt time. Included credits are consumed first, then overage; exceeding the overage cap rejects the whole event. An identical eventId replay returns the original event, even after the period closes; a changed payload conflicts. Both eventId and Idempotency-Key are required.",
        "operationId": "createUsageEvent",
        "parameters": [
          {
            "description": "1–255 printable ASCII characters without spaces. Reuse the same key and payload when retrying. For usage events, eventId is also a durable duplicate-prevention key per subscription.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "example": "usage-intent-123", "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageEventCreateDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "credits": "1.25",
                    "eventId": "request_123",
                    "id": "33333333-3333-4333-8333-333333333333",
                    "subscriptionId": "22222222-2222-4222-8222-222222222222"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageEventResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Record a usage event",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/invoices": {
      "get": {
        "description": "List the latest 100 usage statements in the authenticated merchant and API-key mode, optionally filtered by subscriptionId. Amounts are exact decimal strings. These statements are separate from platform billing and tax invoices.",
        "operationId": "listUsageInvoices",
        "parameters": [
          {
            "in": "query",
            "name": "subscriptionId",
            "required": false,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "baseAmount": "20.00",
                      "createdAt": "2026-10-13T12:00:00.000Z",
                      "currency": "EUR",
                      "id": "44444444-4444-4444-8444-444444444444",
                      "kind": "initial",
                      "overageAmount": "0.00",
                      "paidAt": null,
                      "paymentUrl": null,
                      "periodEnd": "2026-11-13T12:00:00.000Z",
                      "periodStart": "2026-10-13T12:00:00.000Z",
                      "status": "open",
                      "subscriptionId": "22222222-2222-4222-8222-222222222222",
                      "totalAmount": "20.00"
                    }
                  ]
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/UsageInvoiceResponseDto"
                      },
                      "type": "array"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "Latest 100 scoped resources.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List usage invoices",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/plans": {
      "get": {
        "description": "List the latest 100 pricing plans in the authenticated merchant and API-key mode. Decimal values are strings.",
        "operationId": "listUsagePlans",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "code": "starter",
                      "currency": "EUR",
                      "id": "11111111-1111-4111-8111-111111111111",
                      "includedCredits": "1000",
                      "monthlyPrice": "20.00",
                      "name": "Starter",
                      "overageUnitPrice": "0.01",
                      "unit": "request"
                    }
                  ]
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/UsagePlanResponseDto"
                      },
                      "type": "array"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "Latest 100 scoped resources.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List usage plans",
        "tags": ["Usage billing"]
      },
      "post": {
        "description": "Create immutable pricing terms for customer usage, scoped to the authenticated merchant API key and its live/test mode. Monthly price uses currency precision; credits and overage rate allow six fractional digits. Reusing a code with identical terms returns the plan; changed terms conflict.",
        "operationId": "createUsagePlan",
        "parameters": [
          {
            "description": "Optional request key. Plan code is the durable duplicate-prevention key within the shop and mode; changed terms for the same code conflict.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsagePlanCreateDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "code": "starter",
                    "currency": "EUR",
                    "id": "11111111-1111-4111-8111-111111111111",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "name": "Starter",
                    "overageUnitPrice": "0.01",
                    "unit": "request"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsagePlanResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Create a usage plan",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions": {
      "get": {
        "description": "List the latest 100 subscriptions in the authenticated merchant and API-key mode. Decimal values are strings.",
        "operationId": "listUsageSubscriptions",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "autoRenewEnabled": false,
                      "cancelAtPeriodEnd": false,
                      "createdAt": "2026-10-13T12:00:00.000Z",
                      "currency": "EUR",
                      "customerRef": "customer_123",
                      "id": "22222222-2222-4222-8222-222222222222",
                      "includedCredits": "1000",
                      "monthlyPrice": "20.00",
                      "notificationEmailConfigured": false,
                      "notificationEnabled": false,
                      "notificationLocale": "en",
                      "overageAmount": "0.00",
                      "overageCredits": "0",
                      "overageLimit": "10.00",
                      "overageUnitPrice": "0.01",
                      "paymentState": "pay_by_link",
                      "periodEnd": null,
                      "periodStart": null,
                      "planId": "11111111-1111-4111-8111-111111111111",
                      "planName": "Starter",
                      "remainingCredits": "0",
                      "status": "pending_payment",
                      "unit": "request",
                      "usedCredits": "0"
                    }
                  ]
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                      },
                      "type": "array"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "Latest 100 scoped resources.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "List usage subscriptions",
        "tags": ["Usage billing"]
      },
      "post": {
        "description": "Create one noncancelled subscription per opaque customer reference in the authenticated merchant and API-key mode. Idempotency-Key is required. Overage limit is a money string; zero disables overage. Paid plans initially await confirmed payment.",
        "operationId": "createUsageSubscription",
        "parameters": [
          {
            "description": "1–255 printable ASCII characters without spaces. Reuse the same key and payload when retrying. For usage events, eventId is also a durable duplicate-prevention key per subscription.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": { "example": "usage-intent-123", "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageSubscriptionCreateDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Create a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}": {
      "get": {
        "description": "Get one subscription in the authenticated merchant and API-key mode, with its latest 100 events and invoices. Resources in another merchant or mode return the same not-found response as an unknown id.",
        "operationId": "getUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "events": [],
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "invoices": [
                      {
                        "baseAmount": "20.00",
                        "createdAt": "2026-10-13T12:00:00.000Z",
                        "currency": "EUR",
                        "id": "44444444-4444-4444-8444-444444444444",
                        "kind": "initial",
                        "overageAmount": "0.00",
                        "paidAt": null,
                        "paymentUrl": null,
                        "periodEnd": "2026-11-13T12:00:00.000Z",
                        "periodStart": "2026-10-13T12:00:00.000Z",
                        "status": "open",
                        "subscriptionId": "22222222-2222-4222-8222-222222222222",
                        "totalAmount": "20.00"
                      }
                    ],
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionDetailResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Get a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/auto-renew/confirm": {
      "post": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "confirmAutoRenewUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageAutoRenewConfirmDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "confirmAutoRenew for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/auto-renew/disable": {
      "post": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "disableAutoRenewUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageEmptyDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "disableAutoRenew for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/auto-renew/setup": {
      "post": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "setupAutoRenewUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageAutoRenewSetupDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "setupId": "55555555-5555-4555-8555-555555555555",
                    "status": "pending",
                    "url": "https://checkout.stripe.com/c/pay/cs_test_example"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSetupResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "setupAutoRenew for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/cancel": {
      "post": {
        "description": "Cancel at the paid period end, preserving final accrued overage. An unpaid initial subscription cancels immediately. Repeating this request is safe. Scope comes from the authenticated API key.",
        "operationId": "cancelUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageEmptyDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Cancel a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/notifications": {
      "post": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "notificationsUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageNotificationsDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "notifications for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/payments/history": {
      "get": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "paymentHistoryUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "amount": "20.00",
                      "attemptCount": 1,
                      "createdAt": "2026-10-13T12:00:00.000Z",
                      "currency": "EUR",
                      "errorCode": "PROVIDER_OUTCOME_UNKNOWN",
                      "id": "66666666-6666-4666-8666-666666666666",
                      "invoiceId": "44444444-4444-4444-8444-444444444444",
                      "status": "unknown",
                      "updatedAt": "2026-10-13T12:00:00.000Z"
                    }
                  ]
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/UsageAttemptResponseDto"
                      },
                      "type": "array"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "Latest 100 scoped resources.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "paymentHistory for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/payments/recover": {
      "post": {
        "description": "Scoped to the merchant API key and test/live mode. Setup creates a hosted Stripe consent link; it does not authorize a charge. Unknown payment outcomes must be reconciled before recovery.",
        "operationId": "recoverPaymentUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageEmptyDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "recoverPayment for a usage subscription",
        "tags": ["Usage billing"]
      }
    },
    "/v1/usage-billing/subscriptions/{id}/sync": {
      "post": {
        "description": "Reconcile confirmed invoice payments and period boundaries for this subscription. Repeating this request is safe. When automatic renewal is enabled, this operation can advance the persisted Stripe payment attempt; otherwise it reconciles payment links. Scope comes from the authenticated API key.",
        "operationId": "syncUsageSubscription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UsageEmptyDto" }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "autoRenewEnabled": false,
                    "cancelAtPeriodEnd": false,
                    "createdAt": "2026-10-13T12:00:00.000Z",
                    "currency": "EUR",
                    "customerRef": "customer_123",
                    "id": "22222222-2222-4222-8222-222222222222",
                    "includedCredits": "1000",
                    "monthlyPrice": "20.00",
                    "notificationEmailConfigured": false,
                    "notificationEnabled": false,
                    "notificationLocale": "en",
                    "overageAmount": "0.00",
                    "overageCredits": "0",
                    "overageLimit": "10.00",
                    "overageUnitPrice": "0.01",
                    "paymentState": "pay_by_link",
                    "periodEnd": null,
                    "periodStart": null,
                    "planId": "11111111-1111-4111-8111-111111111111",
                    "planName": "Starter",
                    "remainingCredits": "0",
                    "status": "pending_payment",
                    "unit": "request",
                    "usedCredits": "0"
                  }
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSubscriptionResponseDto"
                    }
                  },
                  "required": ["data"],
                  "type": "object"
                }
              }
            },
            "description": "The scoped resource. Duplicate creates return the original resource.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_INPUT_INVALID",
                  "message": "USAGE_INPUT_INVALID",
                  "statusCode": 400
                },
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ApiErrorResponseDto" },
                    {
                      "$ref": "#/components/schemas/ValidationErrorResponseDto"
                    }
                  ]
                }
              }
            },
            "description": "Invalid fields, decimal precision or missing idempotency key. USAGE_INPUT_INVALID / USAGE_AMOUNT_INVALID / USAGE_CREDITS_INVALID / USAGE_IDEMPOTENCY_KEY_REQUIRED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid API key",
                  "statusCode": 401
                },
                "schema": {
                  "$ref": "#/components/schemas/UnauthorizedErrorResponseDto"
                }
              }
            },
            "description": "Missing or invalid merchant API key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SCOPE_INACTIVE",
                  "statusCode": 403
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_SCOPE_INACTIVE: the authenticated merchant or company is inactive."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_SUBSCRIPTION_NOT_FOUND",
                  "statusCode": 404
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_NOT_FOUND / USAGE_SUBSCRIPTION_NOT_FOUND; unknown or another shop/mode."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "USAGE_EVENT_CONFLICT",
                  "statusCode": 409
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "USAGE_PLAN_CONFLICT / USAGE_EVENT_CONFLICT / USAGE_IDEMPOTENCY_CONFLICT / USAGE_SUBSCRIPTION_INACTIVE / USAGE_PERIOD_ENDED / USAGE_OVERAGE_LIMIT_EXCEEDED / USAGE_BUSY."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "IDEMPOTENCY_KEY_REUSED",
                  "statusCode": 422
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "The request conflicts with a previously recorded idempotency key."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "error": "RATE_LIMITED",
                  "errorCode": "RATE_LIMITED",
                  "message": "Too many requests. Retry after the indicated delay.",
                  "status": false,
                  "statusCode": 429
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "RATE_LIMITED: IP, merchant or failed-auth quota exhausted, or auth-in-flight concurrency pressure (Retry-After: 1). Wait Retry-After seconds and retry with the same Idempotency-Key.",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds to reset/full refill (t), per evaluated policy. Absent when disabled; merchant quota is omitted during Redis outages, while IP/auth protection uses replica memory.",
                "schema": {
                  "example": "\"merchant\";r=37;t=4",
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "Evaluated policies (draft-ietf-httpapi-ratelimit-headers-11). q is burst quota; w is the full refill window in seconds.",
                "schema": {
                  "example": "\"merchant\";q=100;w=5",
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Minimum delay in whole seconds before retrying.",
                "schema": { "example": 1, "minimum": 1, "type": "integer" }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_UNAVAILABLE",
                  "statusCode": 502
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_UNAVAILABLE: retry the same intent."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "error": "Service Unavailable",
                  "message": "API_KEY_VALIDATION_UNAVAILABLE",
                  "statusCode": 503
                },
                "schema": {
                  "$ref": "#/components/schemas/AuthenticationUnavailableResponseDto"
                }
              }
            },
            "description": "API key validation unavailable."
          },
          "504": {
            "content": {
              "application/json": {
                "example": {
                  "errorCode": "UPSTREAM_TIMEOUT",
                  "statusCode": 504
                },
                "schema": { "$ref": "#/components/schemas/ApiErrorResponseDto" }
              }
            },
            "description": "UPSTREAM_TIMEOUT: the operation may still complete; retry the same intent."
          }
        },
        "security": [{ "X-API-Key": [] }],
        "summary": "Reconcile a usage subscription",
        "tags": ["Usage billing"]
      }
    }
  },
  "servers": [],
  "tags": [
    {
      "description": "Poll stored merchant transaction status",
      "name": "Transactions"
    },
    { "description": "Create merchant sales and payouts", "name": "Payments" },
    {
      "description": "Request refunds and read stored refund outcomes",
      "name": "Refunds"
    },
    { "description": "Signed merchant event deliveries", "name": "Webhooks" },
    {
      "description": "Create, list and deactivate shareable merchant payment links",
      "name": "Payment links"
    }
  ],
  "webhooks": {
    "refundFailed": {
      "post": {
        "description": "Terminal refund event sent to the original sale callbackUrl, falling back to the merchant default webhook URL. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks. The refund and transaction snapshot stays byte-identical across retries/redrives; retain the maximum cumulative refundedAmount using decimal arithmetic.",
        "operationId": "receiveRefundFailed",
        "parameters": [
          {
            "description": "t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + \".\" + exact raw body)>; never log this header",
            "in": "header",
            "name": "OrsunPay-Signature",
            "required": true,
            "schema": {
              "pattern": "^t=[0-9]+,v1=[a-f0-9]{64}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body id (evt_…); deduplicate only after verifying the signed body",
            "in": "header",
            "name": "OrsunPay-Event-Id",
            "required": true,
            "schema": {
              "pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body type",
            "in": "header",
            "name": "OrsunPay-Event-Type",
            "required": true,
            "schema": { "example": "refund.failed", "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "api_version": "2026-10-31",
                "created": "2026-10-10T10:05:00.000Z",
                "created_at": "2026-10-10T10:05:00.000Z",
                "data": {
                  "refund": {
                    "amount": "5.00",
                    "currency": "EUR",
                    "errorCode": "REFUND_DECLINED",
                    "id": "rf_example",
                    "provider": "stripe",
                    "providerRefundId": "re_example",
                    "reason": "requested_by_customer",
                    "status": "FAILED",
                    "transactionId": "tr_example"
                  },
                  "transaction": {
                    "amount": "12.30",
                    "id": "tr_example",
                    "livemode": true,
                    "orderId": "order_example_001",
                    "refundState": "none",
                    "refundedAmount": "0.00"
                  }
                },
                "id": "evt_0j7s2pft4v8b9t8nj2cra1eg01",
                "livemode": true,
                "type": "refund.failed"
              },
              "schema": { "$ref": "#/components/schemas/RefundWebhookEvent" }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content."
          }
        },
        "security": [],
        "summary": "Refund failed event",
        "tags": ["Webhooks"]
      }
    },
    "refundSucceeded": {
      "post": {
        "description": "Terminal refund event sent to the original sale callbackUrl, falling back to the merchant default webhook URL. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks. The refund and transaction snapshot stays byte-identical across retries/redrives; retain the maximum cumulative refundedAmount using decimal arithmetic.",
        "operationId": "receiveRefundSucceeded",
        "parameters": [
          {
            "description": "t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + \".\" + exact raw body)>; never log this header",
            "in": "header",
            "name": "OrsunPay-Signature",
            "required": true,
            "schema": {
              "pattern": "^t=[0-9]+,v1=[a-f0-9]{64}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body id (evt_…); deduplicate only after verifying the signed body",
            "in": "header",
            "name": "OrsunPay-Event-Id",
            "required": true,
            "schema": {
              "pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body type",
            "in": "header",
            "name": "OrsunPay-Event-Type",
            "required": true,
            "schema": { "example": "refund.succeeded", "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "api_version": "2026-10-31",
                "created": "2026-10-10T10:05:00.000Z",
                "created_at": "2026-10-10T10:05:00.000Z",
                "data": {
                  "refund": {
                    "amount": "5.00",
                    "currency": "EUR",
                    "errorCode": null,
                    "id": "rf_example",
                    "provider": "stripe",
                    "providerRefundId": "re_example",
                    "reason": "requested_by_customer",
                    "status": "SUCCEEDED",
                    "transactionId": "tr_example"
                  },
                  "transaction": {
                    "amount": "12.30",
                    "id": "tr_example",
                    "livemode": true,
                    "orderId": "order_example_001",
                    "refundState": "partial",
                    "refundedAmount": "5.00"
                  }
                },
                "id": "evt_0j7s2pft4v8b9t8nj2cra1eg01",
                "livemode": true,
                "type": "refund.succeeded"
              },
              "schema": { "$ref": "#/components/schemas/RefundWebhookEvent" }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content."
          }
        },
        "security": [],
        "summary": "Refund succeeded event",
        "tags": ["Webhooks"]
      }
    },
    "transactionUpdated": {
      "post": {
        "description": "OrsunPay sends this POST to the transaction callbackUrl after a status update. Verify HMAC-SHA256 over the exact raw body before parsing, using the merchant webhook secret (ADR-010). Reject signature timestamps beyond 300 seconds; compare in constant time. Deliveries are at least once and can arrive out of order. Deduplicate by the signed body id. Secret rotation takes effect immediately (no dual signing); failed deliveries retry for approximately 31 hours. API keys are not sent with webhooks.",
        "operationId": "receiveTransactionUpdated",
        "parameters": [
          {
            "description": "t=<Unix seconds>,v1=<hex HMAC-SHA256(timestamp + \".\" + exact raw body)>; never log this header",
            "in": "header",
            "name": "OrsunPay-Signature",
            "required": true,
            "schema": {
              "pattern": "^t=[0-9]+,v1=[a-f0-9]{64}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body id (evt_…); deduplicate only after verifying the signed body",
            "in": "header",
            "name": "OrsunPay-Event-Id",
            "required": true,
            "schema": {
              "pattern": "^evt_[0-7][0-9a-hjkmnp-tv-z]{25}$",
              "type": "string"
            }
          },
          {
            "description": "Convenience copy of body type",
            "in": "header",
            "name": "OrsunPay-Event-Type",
            "required": true,
            "schema": { "example": "transaction.updated", "type": "string" }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "api_version": "2026-10-31",
                "created_at": "2026-10-10T10:00:00.000Z",
                "data": {
                  "paymentData": {},
                  "transaction": {
                    "action": "SALE",
                    "amount": "12.30",
                    "createdAt": "2026-10-10T09:59:00.000Z",
                    "currency": "EUR",
                    "id": "tr_example",
                    "livemode": true,
                    "orderId": "order_example_001",
                    "status": "SUCCESS"
                  }
                },
                "id": "evt_0j7s2pft4v8b9t8nj2cra1eg00",
                "livemode": true,
                "type": "transaction.updated"
              },
              "schema": { "$ref": "#/components/schemas/WebhookEvent" }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Any 2xx acknowledges delivery. Response body is ignored but must be empty or at most 64 KiB (MERCHANT_WEBHOOK_MAX_RESPONSE_BYTES); a larger body fails the delivery attempt. Prefer HTTP 204 No Content."
          }
        },
        "security": [],
        "summary": "Transaction status event",
        "tags": ["Webhooks"]
      }
    }
  }
}
