{
  "openapi": "3.0.3",
  "info": {
    "title": "Kaskade Payment Solution API",
    "version": "1.1.0",
    "description": "The Kaskade V1 REST API.\n\n**This document is generated from, and validated against, the actual route implementations** — every path below exists in the codebase, and every public V1 route in the codebase appears below. See scripts/validate-openapi.mjs.\n\n**FROZEN — Kaskade API V1.0.0.** See docs/API_V1_CONTRACT.md.",
    "contact": {
      "name": "Kaskade Payment Solution Inc."
    }
  },
  "servers": [
    {
      "url": "https://kaskade.com/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    },
    {
      "signedRequest": []
    }
  ],
  "tags": [
    {
      "name": "Currencies",
      "description": "Discover what can be accepted and paid out."
    },
    {
      "name": "Payments",
      "description": "Take a crypto payment for a USD price."
    },
    {
      "name": "Invoices",
      "description": "Hosted invoices."
    },
    {
      "name": "Payouts",
      "description": "Withdraw settled balance."
    },
    {
      "name": "Account",
      "description": "Fees and balances."
    },
    {
      "name": "Players",
      "description": "Permanent per-player deposit addresses. Requires the casino product."
    },
    {
      "name": "Ramp",
      "description": "Fiat on/off-ramp: buy crypto with card or bank, or sell it for cash."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer ks_live_YOUR_API_KEY"
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Alternative to the Authorization header. Same key."
      },
      "signedRequest": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Kaskade-Signature",
        "description": "HMAC request signing. Send X-Kaskade-Client (your key's Public ID), X-Kaskade-Timestamp (ISO-8601 UTC, within 5 minutes of server time) and X-Kaskade-Signature = base64(HMAC-SHA256(clientSecret, canonical)), where canonical = U+FEFF + METHOD + full URL + clientId + timestamp + rawBody."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 255
        },
        "description": "Optional. Unique value per logical operation. The first response is stored for 24 hours and replayed for any retry with the same key and body. The same key with a different body returns 409 idempotency_conflict."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable sentence. Present on every error since V1 launched."
          },
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "field": {
            "type": "string",
            "description": "The request field the refusal is about, for example `orderId` or `amountUsd`. Present on validation failures from POST /payments and POST /invoices; absent on every other error."
          }
        },
        "description": "`error` is the original field and is always present. `code` is additive; older responses may omit it. `field` is additive too and appears only on validation failures."
      },
      "ErrorCode": {
        "type": "string",
        "description": "Stable machine-readable code. Treat an unrecognised value defensively.",
        "enum": [
          "invalid_api_key",
          "forbidden",
          "validation_error",
          "unsupported_asset",
          "not_found",
          "payment_not_found",
          "payout_not_available",
          "kyc_required",
          "idempotency_conflict",
          "idempotency_in_progress",
          "upstream_unavailable",
          "internal_error",
          "invalid_request",
          "invalid_amount",
          "invalid_currency",
          "idempotency_recovery_required",
          "idempotency_unavailable"
        ]
      },
      "AssetStatus": {
        "type": "string",
        "enum": [
          "live",
          "beta",
          "coming_soon",
          "disabled"
        ],
        "description": "Additive. Product lifecycle. Only `live`/`beta` can take money; check depositAvailable."
      },
      "PaymentStatus": {
        "type": "string",
        "description": "Handle unknown future values defensively.",
        "enum": [
          "waiting",
          "confirming",
          "confirmed",
          "sending",
          "partially_paid",
          "finished",
          "failed",
          "refunded",
          "expired"
        ]
      },
      "Currency": {
        "type": "object",
        "required": [
          "code",
          "enabled"
        ],
        "properties": {
          "code": {
            "type": "string",
            "example": "usdttrc20",
            "description": "Kaskade API identifier. Stable — pass this as payCurrency."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Tether (TRC-20)",
            "description": "Legacy display name. Retained unchanged."
          },
          "network": {
            "type": "string",
            "nullable": true,
            "example": "tron",
            "description": "Legacy network id. Retained unchanged."
          },
          "enabled": {
            "type": "boolean",
            "description": "True when this account can accept the coin today."
          },
          "symbol": {
            "type": "string",
            "example": "USDT",
            "description": "Additive. Ticker as a payer reads it (USDT0 on Polygon)."
          },
          "displayName": {
            "type": "string",
            "example": "Tether",
            "description": "Additive. Full name."
          },
          "networkName": {
            "type": "string",
            "example": "Tron",
            "description": "Additive. Chain name without the token-standard suffix."
          },
          "type": {
            "type": "string",
            "enum": [
              "native",
              "token"
            ],
            "description": "Additive."
          },
          "contract": {
            "type": "string",
            "nullable": true,
            "description": "Additive. Token contract, null for a native coin."
          },
          "decimals": {
            "type": "integer",
            "nullable": true,
            "description": "Additive. On-chain decimals."
          },
          "status": {
            "$ref": "#/components/schemas/AssetStatus"
          },
          "depositAvailable": {
            "type": "boolean",
            "description": "Additive. Can a payment be created in this coin right now?"
          },
          "payoutAvailable": {
            "type": "boolean",
            "description": "Additive. Can money leave on this rail right now?"
          }
        }
      },
      "Payment": {
        "type": "object",
        "description": "The public V1 payment object, produced by an explicit allowlist (src/lib/api/public-dto.ts). Internal columns — Kaskade's margin, webhook bookkeeping, custody identifiers, settlement routing — are never included, and a new database column does not appear here unless it is deliberately added. Money fields are JSON numbers; timestamps are ISO-8601 UTC.",
        "required": [
          "id",
          "status",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Kaskade payment id."
          },
          "npPaymentId": {
            "type": "string",
            "description": "Opaque legacy reference, retained for compatibility with existing reconciliation code and the payment.updated webhook. No guaranteed format or meaning. Deprecated in V2.",
            "nullable": true
          },
          "orderId": {
            "type": "string",
            "description": "Your order reference, echoed back.",
            "nullable": true
          },
          "priceAmount": {
            "type": "number",
            "description": "Fiat price as recorded. In crypto mode the merchant named no fiat price and this is Kaskade's reference valuation at creation — recorded so fees, reports and limits have one currency; it is NOT the amount anyone was asked for. Read pricingMode first.",
            "nullable": true
          },
          "priceCurrency": {
            "type": "string",
            "description": "Fiat currency of priceAmount, e.g. \"usd\". Always a fiat ISO code — never a coin ticker, in either pricing mode.",
            "nullable": true
          },
          "payCurrency": {
            "type": "string",
            "description": "Kaskade coin identifier the payer pays in.",
            "nullable": true
          },
          "payAmount": {
            "type": "number",
            "description": "Crypto amount due, whole units.",
            "nullable": true
          },
          "payAddress": {
            "type": "string",
            "description": "Deposit address for the payer.",
            "nullable": true
          },
          "payExtraId": {
            "type": "string",
            "description": "Memo/destination tag on chains that route by one; null elsewhere.",
            "nullable": true
          },
          "payInHash": {
            "type": "string",
            "description": "On-chain hash of the payer's transfer, once seen.",
            "nullable": true
          },
          "actuallyPaid": {
            "type": "number",
            "description": "Crypto received so far, whole units.",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/PaymentStatus"
          },
          "invoiceUrl": {
            "type": "string",
            "description": "Hosted checkout URL, when one exists.",
            "nullable": true
          },
          "customerChargeUsd": {
            "type": "number",
            "description": "What the payer was charged, USD.",
            "nullable": true
          },
          "platformFeeUsd": {
            "type": "number",
            "description": "Kaskade's fee to you, USD.",
            "nullable": true
          },
          "merchantExtraUsd": {
            "type": "number",
            "description": "Your own added margin, USD.",
            "nullable": true
          },
          "merchantNetUsd": {
            "type": "number",
            "description": "What you net, USD.",
            "nullable": true
          },
          "payoutCoin": {
            "type": "string",
            "description": "Coin the net was/will be settled in.",
            "nullable": true
          },
          "payoutStatus": {
            "type": "string",
            "description": "Settlement progress for your net: none, pending or paid.",
            "nullable": true
          },
          "payoutTxHash": {
            "type": "string",
            "description": "On-chain hash of your settlement, once sent.",
            "nullable": true
          },
          "payoutAt": {
            "type": "string",
            "description": "When your net was settled.",
            "nullable": true,
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "description": "When the payment window closes. In crypto mode this is when the payment REQUEST expires, not when a quoted rate expires — an exact coin amount has no rate to expire.",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last change.",
            "nullable": true,
            "format": "date-time"
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto"
            ],
            "description": "How this was priced. `fiat` — you named a price in your base currency and the coin amount was quoted from it. `crypto` — you named the coin amount itself and the payer owes exactly that."
          },
          "requestedAmount": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the exact amount you asked for, as a decimal string. Null in fiat mode."
          },
          "requestedCurrency": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the Kaskade coin identifier the request was priced in (asset and network). Equal to payCurrency: a coin-denominated request is payable only in the coin it is priced in. Null in fiat mode."
          },
          "amountDueExact": {
            "type": "string",
            "nullable": true,
            "description": "The amount due as a decimal string, in BOTH modes. Same value as payAmount; a string because a chain amount does not always survive a JSON number intact. Use this behind a copy button."
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "number": {
            "type": "string",
            "nullable": true
          },
          "amountUsd": {
            "type": "number",
            "nullable": true,
            "description": "Fiat amount, in your base currency. NULL on a coin-denominated invoice — see requestedAmount."
          },
          "status": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto"
            ],
            "description": "How this was priced. `fiat` — you named a price in your base currency and the coin amount was quoted from it. `crypto` — you named the coin amount itself and the payer owes exactly that."
          },
          "requestedAmount": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the exact amount you asked for, as a decimal string. Null in fiat mode."
          },
          "requestedCurrency": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the Kaskade coin identifier the request was priced in (asset and network). Equal to payCurrency: a coin-denominated request is payable only in the coin it is priced in. Null in fiat mode."
          }
        }
      },
      "Payout": {
        "type": "object",
        "description": "A payout as the public API renders it. Emitted identically by POST /payouts, both GET routes and the payout.updated webhook.",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "submitted",
              "paid",
              "rejected",
              "failed"
            ],
            "description": "pending, approved and submitted are in flight. paid, rejected and failed are terminal. Only paid means money moved."
          },
          "currency": {
            "type": "string",
            "description": "Coin/network being withdrawn, e.g. usdttrc20."
          },
          "amount": {
            "type": "number",
            "description": "Amount in that coin."
          },
          "address": {
            "type": "string",
            "description": "Destination wallet address the funds are sent to."
          },
          "destinationId": {
            "type": "string",
            "nullable": true,
            "description": "The allowlisted payout destination used. Null means your settlement wallet for the coin."
          },
          "destination": {
            "type": "string",
            "nullable": true,
            "description": "That destination's label, copied at request time so it survives the destination being deleted."
          },
          "txHash": {
            "type": "string",
            "nullable": true,
            "description": "On-chain transaction hash. Null until broadcast."
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Why it did not proceed, sanitised for publication. Null unless something went wrong."
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "Your own free-text reference, echoed back. Not an idempotency key."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "paidAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Set only once status is paid."
          }
        }
      },
      "PayoutDestination": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "currency": {
            "type": "string",
            "description": "Coin/network. Note the create request field is named `coin`."
          },
          "address": {
            "type": "string"
          },
          "tag": {
            "type": "string",
            "nullable": true
          },
          "whitelistStatus": {
            "type": "string",
            "description": "pending until a person approves the address; approved once it may be paid."
          },
          "payable": {
            "type": "boolean",
            "description": "Derived: true when whitelistStatus is approved."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Player": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "externalId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "coin": {
            "type": "string"
          },
          "depositAddress": {
            "type": "string"
          },
          "depositTag": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "RampOrder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "checkoutUrl": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "PaymentCreated": {
        "type": "object",
        "description": "The response to Create a payment. Deliberately NARROWER than the retrieved payment object, and it uses `priceUsd` where the retrieved object uses `priceAmount`/`priceCurrency`. This asymmetry predates V1 and is preserved rather than corrected, because changing either shape would break existing integrations. Retrieve the payment for the full object.",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "npPaymentId": {
            "type": "string",
            "description": "Opaque legacy reference. See the Payment object.",
            "nullable": true
          },
          "priceUsd": {
            "type": "number",
            "nullable": true,
            "description": "The fiat price you asked for. NULL in crypto mode, where you asked for a coin amount instead — see requestedAmount."
          },
          "payAddress": {
            "type": "string",
            "description": " Deposit address for the payer.",
            "nullable": true
          },
          "payExtraId": {
            "type": "string",
            "description": "Memo/destination tag where the chain needs one.",
            "nullable": true
          },
          "payAmount": {
            "type": "number",
            "description": "Crypto amount due.",
            "nullable": true
          },
          "payCurrency": {
            "type": "string",
            "description": "Coin the payer pays in.",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/PaymentStatus"
          },
          "expiresAt": {
            "type": "string",
            "description": "When the payment window closes. In crypto mode this is when the payment REQUEST expires, not when a quoted rate expires — an exact coin amount has no rate to expire.",
            "nullable": true,
            "format": "date-time"
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto"
            ],
            "description": "How this was priced. `fiat` — you named a price in your base currency and the coin amount was quoted from it. `crypto` — you named the coin amount itself and the payer owes exactly that."
          },
          "requestedAmount": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the exact amount you asked for, as a decimal string. Null in fiat mode."
          },
          "requestedCurrency": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the Kaskade coin identifier the request was priced in (asset and network). Equal to payCurrency: a coin-denominated request is payable only in the coin it is priced in. Null in fiat mode."
          },
          "amountDueExact": {
            "type": "string",
            "nullable": true,
            "description": "The amount due as a decimal string, in BOTH modes. Same value as payAmount; a string because a chain amount does not always survive a JSON number intact. Use this behind a copy button."
          }
        }
      },
      "WebhookPayment": {
        "type": "object",
        "description": "The payment representation inside payment.updated. An explicit allowlist, narrower than the REST object.",
        "properties": {
          "id": {
            "type": "string"
          },
          "npPaymentId": {
            "type": "string",
            "description": "Opaque legacy reference.",
            "nullable": true
          },
          "orderId": {
            "type": "string",
            "description": "Your order reference.",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/PaymentStatus"
          },
          "priceAmount": {
            "type": "number",
            "description": "Fiat price. In crypto mode, Kaskade's reference valuation — read pricingMode.",
            "nullable": true
          },
          "priceCurrency": {
            "type": "string",
            "description": "Fiat currency.",
            "nullable": true
          },
          "payAmount": {
            "type": "number",
            "description": "Crypto amount due.",
            "nullable": true
          },
          "payCurrency": {
            "type": "string",
            "description": "Coin.",
            "nullable": true
          },
          "payAddress": {
            "type": "string",
            "description": "Deposit address.",
            "nullable": true
          },
          "payExtraId": {
            "type": "string",
            "description": "Memo/tag where applicable.",
            "nullable": true
          },
          "actuallyPaid": {
            "type": "number",
            "description": "Crypto received so far.",
            "nullable": true
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto"
            ],
            "description": "How this was priced. `fiat` — you named a price in your base currency and the coin amount was quoted from it. `crypto` — you named the coin amount itself and the payer owes exactly that."
          },
          "requestedAmount": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the exact amount you asked for, as a decimal string. Null in fiat mode."
          },
          "requestedCurrency": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the Kaskade coin identifier the request was priced in (asset and network). Equal to payCurrency: a coin-denominated request is payable only in the coin it is priced in. Null in fiat mode."
          },
          "amountDueExact": {
            "type": "string",
            "nullable": true,
            "description": "The amount due as a decimal string, in BOTH modes. Same value as payAmount; a string because a chain amount does not always survive a JSON number intact. Use this behind a copy button."
          }
        }
      },
      "WebhookDeposit": {
        "type": "object",
        "description": "A confirmed player deposit. Casino-gated accounts only.",
        "properties": {
          "id": {
            "type": "string"
          },
          "playerId": {
            "type": "string"
          },
          "externalId": {
            "type": "string",
            "description": "Your own id for the player."
          },
          "playerName": {
            "type": "string"
          },
          "coin": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "address": {
            "type": "string",
            "description": "The player's permanent deposit address."
          },
          "txHash": {
            "type": "string",
            "nullable": true
          },
          "blockTime": {
            "type": "string",
            "format": "date-time"
          },
          "confirmedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookInvoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "amountUsd": {
            "type": "number",
            "nullable": true,
            "description": "Fiat amount. Null on a coin-denominated invoice."
          },
          "number": {
            "type": "string"
          },
          "paymentId": {
            "type": "string",
            "nullable": true
          },
          "pricingMode": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto"
            ],
            "description": "How this was priced. `fiat` — you named a price in your base currency and the coin amount was quoted from it. `crypto` — you named the coin amount itself and the payer owes exactly that."
          },
          "requestedAmount": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the exact amount you asked for, as a decimal string. Null in fiat mode."
          },
          "requestedCurrency": {
            "type": "string",
            "nullable": true,
            "description": "In crypto mode, the Kaskade coin identifier the request was priced in (asset and network). Equal to payCurrency: a coin-denominated request is payable only in the coin it is priced in. Null in fiat mode."
          }
        }
      }
    }
  },
  "paths": {
    "/currencies": {
      "get": {
        "tags": [
          "Currencies"
        ],
        "operationId": "listCurrencies",
        "summary": "List currencies this account can accept",
        "description": "By default returns LIVE coins only — unchanged from launch. Pass `include=upcoming` to additionally receive announced, non-transactional assets, which carry `enabled:false` and `depositAvailable:false`.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "upcoming",
                "all"
              ]
            },
            "description": "Opt in to announced assets."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currencies": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Currency"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/currencies/{code}": {
      "get": {
        "tags": [
          "Currencies"
        ],
        "operationId": "getCurrency",
        "summary": "Metadata and live minimum for one currency",
        "description": "Answers for ANY ticker, including ones this account cannot accept.",
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Currency"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "minUsd": {
                              "type": "number",
                              "nullable": true,
                              "description": "Live minimum payable amount in USD, or null when unavailable."
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/rates/estimate": {
      "get": {
        "tags": [
          "Currencies"
        ],
        "operationId": "estimateRate",
        "summary": "Live USD to crypto estimate",
        "parameters": [
          {
            "name": "amount",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "amountUsd": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "estimatedAmount": {
                      "type": "number"
                    },
                    "rate": {
                      "type": "number",
                      "description": "USD per coin."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing parameters, or a currency we cannot price.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "No pricing source available right now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/fees": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getFees",
        "summary": "Fee schedule for this account",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "platformFeePercent": {
                      "type": "number"
                    },
                    "merchantExtraPercent": {
                      "type": "number"
                    },
                    "feeMode": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getBalance",
        "summary": "Available custody balance per coin",
        "description": "Direct-settlement accounts receive an empty object: nothing is held for them.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "balances": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "number"
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Balance source unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payments": {
      "post": {
        "tags": [
          "Payments"
        ],
        "operationId": "createPayment",
        "summary": "Create a payment",
        "description": "Creates a **direct payment**: Kaskade allocates a deposit address and returns it to you with the exact amount due, so you can render your own payment screen. If you would rather we hosted the checkout and gave you a shareable link, call `POST /invoices` instead.\n\n**Price the payment one of two ways — send exactly one amount.**\n\n**Fiat-denominated (`priceUsd`)** — the payment is priced in your base currency and Kaskade calculates the cryptocurrency amount due at the live rate. `{\"priceUsd\": 100, \"payCurrency\": \"usdttrc20\"}` means *$100 worth* of USDT on Tron — approximately 100 USDT, not exactly 100. This is V1.0 behaviour and is unchanged.\n\n**Coin-denominated (`payAmount` + `payCurrency`)** — the payment is priced directly in the coin, as a decimal STRING. No fiat conversion determines the customer principal. `{\"payAmount\": \"100\", \"payCurrency\": \"usdttrc20\"}` means the customer owes **exactly 100 USDT on TRON**; the platform fee is not added to it. A JSON number is rejected — an exact coin amount must be quoted.\n\nSending both amounts, or neither, is a `validation_error`.\n\n**The ticker encodes the network.** `usdttrc20` (USDT on Tron) and `usdterc20` (USDT on Ethereum) are different rails and are never interchangeable; a bare `usdt` is rejected because it does not say which chain the funds should arrive on. There is no separate network field. Discover valid tickers with `GET /currencies`.\n\n**Same asset, same network only.** In V1.1 a coin-denominated payment is settled by that asset on that network and nothing else — Kaskade performs no cross-asset or cross-network conversion.\n\nThe response carries `id`, `payCurrency`, `payAmount`, `amountDueExact`, `payAddress`, `status`, `expiresAt` and `pricingMode` (`fiat` or `crypto`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "description": "Give EXACTLY ONE amount. `priceUsd` prices the payment in your base currency (V1.0 behaviour, unchanged); `payAmount` prices it in the coin itself. Sending both, or neither, is a validation_error.",
                "oneOf": [
                  {
                    "title": "FiatDenominated",
                    "type": "object",
                    "required": [
                      "priceUsd",
                      "payCurrency"
                    ],
                    "properties": {
                      "priceUsd": {
                        "type": "number",
                        "description": "Positive fiat price, in your base currency. Quoted into `payCurrency` at the live rate."
                      },
                      "payCurrency": {
                        "type": "string",
                        "description": "Kaskade coin identifier from GET /currencies. Encodes the asset AND its network."
                      },
                      "orderId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "orderDescription": {
                        "type": "string",
                        "maxLength": 500
                      }
                    }
                  },
                  {
                    "title": "CryptoDenominated",
                    "type": "object",
                    "required": [
                      "payAmount",
                      "payCurrency"
                    ],
                    "properties": {
                      "payAmount": {
                        "type": "string",
                        "description": "Exact amount of `payCurrency`, as a decimal STRING (\"100\", \"0.005\"). The payer owes precisely this — no exchange rate is involved in producing it. A JSON number is rejected: a coin amount does not survive a float intact. Precision is the asset's own, capped at 8 decimal places in this release; anything finer is refused rather than rounded. The network is part of `payCurrency` (usdttrc20, usdterc20, …), so a bare \"usdt\" is refused.",
                        "example": "0.005"
                      },
                      "payCurrency": {
                        "type": "string",
                        "description": "Kaskade coin identifier from GET /currencies. Encodes the asset AND its network."
                      },
                      "orderId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "orderDescription": {
                        "type": "string",
                        "maxLength": 500
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "$ref": "#/components/schemas/PaymentCreated"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or the coin is not available to this account (unsupported_asset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency-Key reused with a different body, or the first attempt is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Payments"
        ],
        "operationId": "listPayments",
        "summary": "List payments",
        "description": "Returns the most recent items, newest first, capped server-side. There are no pagination parameters on this endpoint today.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payment"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payments/{id}": {
      "get": {
        "tags": [
          "Payments"
        ],
        "operationId": "getPayment",
        "summary": "Retrieve a payment (refreshes status)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment": {
                      "$ref": "#/components/schemas/Payment"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such payment on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/invoices": {
      "post": {
        "tags": [
          "Invoices"
        ],
        "operationId": "createInvoice",
        "summary": "Create a hosted invoice",
        "description": "Creates a **hosted invoice** and returns a shareable Kaskade checkout URL. The `invoice.url` in the response is a page hosted by Kaskade — give it to your customer and they pay there. Use this when you do not want to build a payment screen; use `POST /payments` when you want the deposit address and amount programmatically.\n\n**Price the invoice one of two ways — send exactly one amount.**\n\n**Fiat-denominated (`amountUsd`)** — the invoice is priced in your base currency and Kaskade calculates the cryptocurrency amount due. `{\"amountUsd\": 100, \"payCurrency\": \"usdttrc20\"}` means *$100 worth* of USDT on Tron. `payCurrency` is optional here: set it to lock the invoice to one coin, omit it to let the customer choose any supported coin.\n\n**Coin-denominated (`payAmount` + `payCurrency`)** — the invoice is priced directly in the coin, as a decimal STRING, and `payCurrency` is REQUIRED. `{\"payAmount\": \"100\", \"payCurrency\": \"usdttrc20\"}` means the invoice is for **exactly 100 USDT on TRON**, payable in that asset on that network only. A JSON number is rejected.\n\nSending both amounts, or neither, is a `validation_error`.\n\n**The ticker encodes the network.** `usdttrc20` (USDT on Tron) and `usdterc20` (USDT on Ethereum) are different rails and are never interchangeable; a bare `usdt` is rejected. There is no separate network field. Discover valid tickers with `GET /currencies`.\n\n**Same asset, same network only.** A `usdttrc20` invoice is not settled by USDT sent on Ethereum, and a `usdterc20` invoice is not settled by USDT sent on Tron. Cross-asset and cross-network conversion is not part of V1.1.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "description": "Give EXACTLY ONE amount. `amountUsd` prices the invoice in your base currency (V1.0 behaviour, unchanged); `payAmount` prices it in the coin itself and requires `payCurrency`. Sending both, or neither, is a validation_error.",
                "oneOf": [
                  {
                    "title": "FiatDenominated",
                    "type": "object",
                    "required": [
                      "amountUsd"
                    ],
                    "properties": {
                      "amountUsd": {
                        "type": "number",
                        "description": "Positive fiat amount, in your base currency."
                      },
                      "orderId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "orderDescription": {
                        "type": "string",
                        "maxLength": 500
                      },
                      "customerEmail": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 200
                      },
                      "payCurrency": {
                        "type": "string",
                        "description": "Optional. Locks the invoice to one coin."
                      }
                    }
                  },
                  {
                    "title": "CryptoDenominated",
                    "type": "object",
                    "required": [
                      "payAmount",
                      "payCurrency"
                    ],
                    "properties": {
                      "payAmount": {
                        "type": "string",
                        "description": "Exact amount of `payCurrency`, as a decimal STRING (\"100\", \"0.005\"). The payer owes precisely this — no exchange rate is involved in producing it. A JSON number is rejected: a coin amount does not survive a float intact. Precision is the asset's own, capped at 8 decimal places in this release; anything finer is refused rather than rounded. The network is part of `payCurrency` (usdttrc20, usdterc20, …), so a bare \"usdt\" is refused.",
                        "example": "100"
                      },
                      "payCurrency": {
                        "type": "string",
                        "description": "REQUIRED in this branch: the coin the invoice is priced in. The invoice is payable in this coin only."
                      },
                      "orderId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "orderDescription": {
                        "type": "string",
                        "maxLength": 500
                      },
                      "customerEmail": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 200
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoice": {
                      "$ref": "#/components/schemas/Invoice"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Invoices"
        ],
        "operationId": "listInvoices",
        "summary": "List invoices",
        "description": "Returns the most recent items, newest first, capped server-side. There are no pagination parameters on this endpoint today.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoices": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invoice"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "operationId": "getInvoice",
        "summary": "Retrieve an invoice",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invoice": {
                      "$ref": "#/components/schemas/Invoice"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payouts": {
      "post": {
        "tags": [
          "Payouts"
        ],
        "operationId": "createPayout",
        "summary": "Request a payout",
        "description": "Subject to KYC, rail availability, allowlisted destinations and operator release.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "currency",
                  "amount"
                ],
                "properties": {
                  "currency": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "number"
                  },
                  "destinationId": {
                    "type": "string",
                    "description": "An allowlisted payout destination id."
                  },
                  "reference": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Requested",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payout": {
                      "$ref": "#/components/schemas/Payout"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Payout not available (rails, balance, destination), or idempotency conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Payouts"
        ],
        "operationId": "listPayouts",
        "summary": "List payouts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Maximum rows to return."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payouts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payout"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payouts/{id}": {
      "get": {
        "tags": [
          "Payouts"
        ],
        "operationId": "getPayout",
        "summary": "Retrieve a payout",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payout": {
                      "$ref": "#/components/schemas/Payout"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payout-destinations": {
      "get": {
        "tags": [
          "Payouts"
        ],
        "operationId": "listPayoutDestinations",
        "summary": "List allowlisted destinations",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "destinations": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PayoutDestination"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Payouts"
        ],
        "operationId": "createPayoutDestination",
        "summary": "Add a payout destination",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "label",
                  "currency",
                  "address"
                ],
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "currency": {
                    "type": "string",
                    "maxLength": 32,
                    "description": "Coin/network, e.g. usdttrc20. Returned as `currency` on the destination."
                  },
                  "address": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 256
                  },
                  "tag": {
                    "type": "string",
                    "maxLength": 64,
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "destination": {
                      "$ref": "#/components/schemas/PayoutDestination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/players": {
      "post": {
        "tags": [
          "Players"
        ],
        "operationId": "createPlayer",
        "summary": "Create (or return) a player and their permanent deposit address",
        "description": "Requires the casino product on the account, otherwise 403. Naturally idempotent on externalId: calling twice returns the same player and the same permanent address. TRON only today.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "externalId",
                  "name"
                ],
                "properties": {
                  "externalId": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "coin": {
                    "type": "string",
                    "description": "Optional. Defaults to the account's player coin."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "player": {
                      "$ref": "#/components/schemas/Player"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed, or an unsupported coin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The casino product is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Duplicate, or idempotency conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Players"
        ],
        "operationId": "listPlayers",
        "summary": "List players",
        "description": "Returns the most recent items, newest first, capped server-side. There are no pagination parameters on this endpoint today.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "players": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Player"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The casino product is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/players/{id}": {
      "get": {
        "tags": [
          "Players"
        ],
        "operationId": "getPlayer",
        "summary": "Retrieve a player",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "player": {
                      "$ref": "#/components/schemas/Player"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The casino product is not enabled for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ramp/onramp": {
      "post": {
        "tags": [
          "Ramp"
        ],
        "operationId": "createOnramp",
        "summary": "Create a fiat on-ramp order",
        "description": "Returns 503 when the fiat ramp is not enabled for the platform.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "priceUsd"
                ],
                "properties": {
                  "priceUsd": {
                    "type": "number"
                  },
                  "payCurrency": {
                    "type": "string"
                  },
                  "fiat": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 3
                  },
                  "externalCustomerId": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "redirectUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "orderId": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ramp": {
                      "$ref": "#/components/schemas/RampOrder"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Ramp provider error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/ramp/offramp": {
      "post": {
        "tags": [
          "Ramp"
        ],
        "operationId": "createOfframp",
        "summary": "Create a fiat off-ramp order",
        "description": "Returns 503 when the fiat ramp is not enabled for the platform.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "cryptoAmount",
                  "walletAddress"
                ],
                "properties": {
                  "cryptoAmount": {
                    "type": "number"
                  },
                  "walletAddress": {
                    "type": "string",
                    "minLength": 10
                  },
                  "payCurrency": {
                    "type": "string"
                  },
                  "fiat": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 3
                  },
                  "externalCustomerId": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "redirectUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "orderId": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ramp": {
                      "$ref": "#/components/schemas/RampOrder"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Ramp provider error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "An Idempotency-Key was supplied but could not be honoured. Nothing was created; retry the identical request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/ramp/orders/{id}": {
      "get": {
        "tags": [
          "Ramp"
        ],
        "operationId": "getRampOrder",
        "summary": "Retrieve a ramp order",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ramp": {
                      "$ref": "#/components/schemas/RampOrder"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "x-webhooks": {
    "payment.updated": {
      "post": {
        "summary": "A payment changed status",
        "description": "Signed with x-kaskade-signature. Delivered up to 3 times.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Event id, stable per payment+status."
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "payment.updated"
                    ]
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "payment": {
                        "$ref": "#/components/schemas/WebhookPayment"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          }
        }
      }
    },
    "invoice.paid": {
      "post": {
        "summary": "An invoice was paid",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Event id, stable per object+transition."
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "invoice.paid"
                    ]
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "invoice": {
                        "$ref": "#/components/schemas/WebhookInvoice"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          }
        }
      }
    },
    "payout.updated": {
      "post": {
        "summary": "A payout changed status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Event id, stable per object+transition."
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "payout.updated"
                    ]
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "payout": {
                        "$ref": "#/components/schemas/Payout"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          }
        }
      }
    },
    "deposit.confirmed": {
      "post": {
        "summary": "A player deposit confirmed on chain",
        "description": "Casino product only.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Event id, stable per object+transition."
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "deposit.confirmed"
                    ]
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "deposit": {
                        "$ref": "#/components/schemas/WebhookDeposit"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          }
        }
      }
    }
  }
}
