{
    "openapi": "3.1.0",
    "info": {
        "title": "Rune Pay API",
        "version": "1.0",
        "summary": "Accept cryptocurrency payments and send payouts.",
        "description": "Every response carries the same envelope: `data`, `message`, `error`, `status`, `version`.\n\n## Authentication\nThere are two kinds of key, deliberately separated. A **merchant key** (`rp_sec_…`) can take money in. A **payout key** (`rp_out_…`) can send money out. A key that leaks from your checkout page therefore cannot drain your balance.\n\n**Keys are shown once** — The raw key is displayed only at creation. Rune Pay stores nothing but its SHA-256 hash, so a database leak does not expose usable credentials — and we genuinely cannot recover it for you. If you lose it, revoke it and create another.\n\nPrefixes are checked before the database is touched: a token that does not start with the right prefix is rejected as malformed, which means sending a payout key to a payment endpoint fails immediately and tells you so.\n\n## Amounts and precision\n**Never parse an amount as a float** — Rune Pay returns every monetary value as a **decimal string** and computes internally with arbitrary precision. IEEE-754 doubles cannot represent 0.1 exactly, and 8-decimal BTC values exceed the safe integer range of a JavaScript number once denominated in satoshis. Use a decimal library — `BigDecimal`, `decimal.Decimal`, `bcmath`, `big.js`.\n\nThe exchange rate is locked when the payment is created and stored on it as `rate`. A customer who pays 20 minutes later still pays the quoted crypto amount — the volatility between quote and settlement is ours, not theirs.\n\n## Rate limits\nRequests are limited **per API key**, at 60 per minute on the default plan. The window is a rolling 60 seconds.\n\n`error.retry_after` is the number of seconds until the window clears. Wait that long rather than retrying immediately — a tight retry loop keeps the window permanently full and locks you out for longer than backing off would.\n\n**Do not poll for payment status** — Polling `GET /payment/{track_id}` in a loop is the usual way people hit this limit. Use callbacks: they arrive within seconds of the block confirming and cost you no requests at all. Poll only as a reconciliation sweep, minutes apart.\n\n## Idempotency and duplicates\nPayments and payouts handle repeat requests differently, because the consequences of a duplicate are not the same.\n\n**Always send order_id on payouts** — If a payout request times out you cannot tell whether it was queued. Without `order_id`, retrying may send the funds twice, and an on-chain transaction cannot be recalled. With it, retrying is safe.",
        "contact": {
            "name": "Rune Pay",
            "url": "https://rpay.gg/docs"
        }
    },
    "servers": [
        {
            "url": "https://rpay.gg/api/v1",
            "description": "Production"
        }
    ],
    "security": [
        {
            "merchantKey": []
        }
    ],
    "tags": [
        {
            "name": "Reference data",
            "description": "Public endpoints. No API key required, no rate limit tied to a key. Cache these — they change rarely."
        },
        {
            "name": "Payments",
            "description": "Taking money in. Requires a merchant key (`rp_sec_…`)."
        },
        {
            "name": "Payouts",
            "description": "Sending money out. Requires a payout key (`rp_out_…`) and the custodial wallet."
        }
    ],
    "paths": {
        "/common/currencies": {
            "get": {
                "operationId": "getCurrencies",
                "summary": "Every coin and network Rune Pay knows about, with limits and live availability.",
                "description": "Returns coins grouped by symbol, each with the networks it can be paid on. Build your checkout selector from this rather than hard-coding a list, because availability changes: a network under maintenance, or one whose provider is unreachable, reports `\"status\": \"unavailable\"` and must not be offered to a customer. A coin's top-level `status` is `true` when at least one of its networks is active.\n\n**`data` is an object keyed by coin symbol, not an array**, and `networks` is keyed by network id. Iterate the values (`Object.values(data)`) rather than indexing by position. Each network also repeats its own `id` so a value-only iteration still knows what it is holding.",
                "tags": [
                    "Reference data"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "USDT": {
                                            "symbol": "USDT",
                                            "name": "Tether",
                                            "color": "#26a17b",
                                            "icon": "https://rpay.gg/assets/coins/usdt.svg",
                                            "status": true,
                                            "networks": {
                                                "TRC20": {
                                                    "id": "TRC20",
                                                    "network": "TRON (TRC20)",
                                                    "chain": "tron",
                                                    "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
                                                    "decimals": 6,
                                                    "confirmations": 20,
                                                    "min_deposit": "1",
                                                    "min_withdrawal": "10",
                                                    "withdrawal_fee": "1",
                                                    "needs_memo": false,
                                                    "status": "active"
                                                }
                                            }
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/common/fiat-currencies": {
            "get": {
                "operationId": "getFiatCurrencies",
                "summary": "Fiat currencies accepted in the `currency` field when pricing a payment.",
                "description": "You price in fiat and the customer pays in crypto; this is the list of fiat currencies you may price in. Sending an unlisted currency is rejected at creation.",
                "tags": [
                    "Reference data"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "USD": {
                                            "symbol": "USD",
                                            "name": "US Dollar",
                                            "sign": "$"
                                        },
                                        "EUR": {
                                            "symbol": "EUR",
                                            "name": "Euro",
                                            "sign": "€"
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/common/prices": {
            "get": {
                "operationId": "getPrices",
                "summary": "The rates Rune Pay is currently quoting, per coin, in USD.",
                "description": "Useful for showing an approximate crypto amount before the customer commits. It is **indicative only**: the binding rate is the one locked onto the payment at creation and returned as `rate`. Never compute the amount to charge from this endpoint — use `pay_amount` from the payment itself.",
                "tags": [
                    "Reference data"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "BTC": "64210.55",
                                        "USDT": "1.0002",
                                        "ETH": "3120.40"
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/common/networks": {
            "get": {
                "operationId": "getNetworks",
                "summary": "Every network as a flat list, keyed by the identifier you pass as `network`.",
                "description": "The same information as currencies, without the grouping. Currencies nests networks under their coin, which is what you want for a checkout selector and not what you want when the question is simply \"what exactly do I put in the `network` field\".\n\nKeyed by network id. Only offer the ones reporting `\"status\": \"active\"`.",
                "tags": [
                    "Reference data"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "TRC20": {
                                            "id": "TRC20",
                                            "currency": "USDT",
                                            "network": "TRON (TRC20)",
                                            "chain": "tron",
                                            "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
                                            "decimals": 6,
                                            "confirmations": 20,
                                            "min_deposit": "1",
                                            "min_withdrawal": "10",
                                            "withdrawal_fee": "1",
                                            "needs_memo": false,
                                            "status": "active"
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/common/status": {
            "get": {
                "operationId": "getStatus",
                "summary": "Per-network health, as Rune Pay sees it right now.",
                "description": "`operational` reflects whether the blockchain provider for that network is reachable and in sync. A network can be enabled but not operational — during a provider outage, for instance. Treat a non-operational network as unavailable for checkout even if it appears in the currencies list.",
                "tags": [
                    "Reference data"
                ],
                "security": [],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "networks": {
                                            "BTC": {
                                                "id": "BTC",
                                                "currency": "BTC",
                                                "network": "Bitcoin",
                                                "provider": "esplora",
                                                "operational": true
                                            },
                                            "TRC20": {
                                                "id": "TRC20",
                                                "currency": "USDT",
                                                "network": "TRON (TRC20)",
                                                "provider": "trongrid",
                                                "operational": true
                                            }
                                        },
                                        "time": 1754092800
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/payment/invoice": {
            "post": {
                "operationId": "createInvoice",
                "summary": "Creates a payment and returns a hosted checkout URL to redirect the customer to.",
                "description": "The quickest way to take a payment. Rune Pay hosts the checkout page — coin selection, address, QR code, countdown, confirmation tracking — so you only handle the redirect and the callback.\n\nEvery field is optional except `amount`; anything you omit falls back to the defaults configured on the API key, so you can move settings out of your code and into the dashboard. A field sent in the request overrides the key default for that one payment.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "description": "Amount to charge, in `currency`. Must be greater than 0.",
                                        "example": 25
                                    },
                                    "currency": {
                                        "type": "string",
                                        "description": "Fiat currency to price in. Defaults to `USD`.",
                                        "example": "USD"
                                    },
                                    "pay_currency": {
                                        "type": "string",
                                        "description": "Preselect the coin the customer pays in, e.g. `USDT`. Must be accepted by the key.",
                                        "example": "USDT"
                                    },
                                    "network": {
                                        "type": "string",
                                        "description": "Preselect the network, e.g. `TRC20`. Takes precedence over `pay_currency`.",
                                        "example": "TRC20"
                                    },
                                    "order_id": {
                                        "type": "string",
                                        "description": "Your own reference. Returned on every callback and searchable in the dashboard. Max 100 chars.",
                                        "example": "ORDER-1043"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Shown to the customer on the checkout page. Max 500 chars.",
                                        "example": "Rune verification — 1 year"
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Customer email. Prefills the receipt field on checkout.",
                                        "example": "buyer@example.com"
                                    },
                                    "callback_url": {
                                        "type": "string",
                                        "description": "Where to POST status changes. Overrides the key default. Must be a public HTTPS URL.",
                                        "example": "https://example.com/hooks/runepay"
                                    },
                                    "return_url": {
                                        "type": "string",
                                        "description": "Where the customer lands after paying.",
                                        "example": "https://example.com/thanks"
                                    },
                                    "lifetime": {
                                        "type": "integer",
                                        "description": "Minutes before the payment expires. 15–2880 (48 h). Default 60.",
                                        "example": 60
                                    },
                                    "under_paid_coverage": {
                                        "type": "number",
                                        "description": "Percent shortfall to still accept, 0–60. `2` accepts a payment 2% short — useful when the customer's wallet deducts its own fee.",
                                        "example": 2
                                    },
                                    "fee_paid_by_payer": {
                                        "type": "boolean",
                                        "description": "When true, the processing fee is added on top of the amount so you receive the full `amount`.",
                                        "example": true
                                    },
                                    "to_currency": {
                                        "type": "string",
                                        "description": "Accepted for OxaPay compatibility and ignored: every payment is already converted to your settlement coin and delivered to your settlement address automatically. Configure both in the dashboard under Settlement.",
                                        "example": "USDT"
                                    },
                                    "auto_withdrawal": {
                                        "type": "boolean",
                                        "description": "Accepted for OxaPay compatibility and ignored: settlement already forwards every confirmed payment to your own wallet — there is nothing extra to switch on.",
                                        "example": false
                                    },
                                    "mixed_payment": {
                                        "type": "boolean",
                                        "description": "Allow the invoice to be settled by several transactions instead of one.",
                                        "example": true
                                    },
                                    "sandbox": {
                                        "type": "boolean",
                                        "description": "Simulate the payment without watching a real chain. See Testing.",
                                        "example": false
                                    }
                                },
                                "required": [
                                    "amount"
                                ]
                            },
                            "example": {
                                "amount": 25,
                                "currency": "USD",
                                "order_id": "ORDER-1043",
                                "description": "Rune verification — 1 year",
                                "callback_url": "https://example.com/hooks/runepay",
                                "return_url": "https://example.com/thanks",
                                "lifetime": 60
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "track_id": "INV_9F2K4M1Q7X",
                                        "payment_url": "https://rpay.gg/checkout/INV_9F2K4M1Q7X",
                                        "expired_at": 1754096400,
                                        "date": 1754092800
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 201,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "The amount is below the network minimum, or no exchange rate is available for the pair.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, malformed or revoked API key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation. `error.fields` names which.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "No blockchain network is currently available. Retry shortly; do not treat as fatal.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/white-label": {
            "post": {
                "operationId": "createWhiteLabel",
                "summary": "Same engine, no hosted page: returns the address and exact amount for your own UI.",
                "description": "Use this when checkout must stay inside your own interface. You get the deposit address, the exact crypto amount and a QR code URL, and you render the page.\n\nThe trade-off is that everything the hosted page does — the countdown, the \"waiting for confirmations\" state, partial-payment handling, expiry — becomes yours to build. `pay_currency` is required here because there is no page for the customer to choose a coin on.\n\nThe response still carries `payment_url`. You do not need it — that is the page you are replacing — but it exists for every payment, and it is the link to send somebody on their phone, or the fallback while your own page is being built.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "description": "Amount to charge, in `currency`.",
                                        "example": 25
                                    },
                                    "pay_currency": {
                                        "type": "string",
                                        "description": "The coin the customer will pay in, e.g. `USDT`.",
                                        "example": "USDT"
                                    },
                                    "network": {
                                        "type": "string",
                                        "description": "Which network, when the coin exists on several. Without it, the first accepted network for that coin is used.",
                                        "example": "TRC20"
                                    },
                                    "currency": {
                                        "type": "string",
                                        "description": "Fiat currency to price in. Defaults to `USD`.",
                                        "example": "USD"
                                    },
                                    "order_id": {
                                        "type": "string",
                                        "description": "Your own reference.",
                                        "example": "ORDER-1044"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Stored on the payment and echoed in callbacks.",
                                        "example": "Top-up"
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Customer email.",
                                        "example": "buyer@example.com"
                                    },
                                    "callback_url": {
                                        "type": "string",
                                        "description": "Where to POST status changes.",
                                        "example": "https://example.com/hooks/runepay"
                                    },
                                    "lifetime": {
                                        "type": "integer",
                                        "description": "Minutes before expiry. 15–2880.",
                                        "example": 60
                                    },
                                    "under_paid_coverage": {
                                        "type": "number",
                                        "description": "Percent shortfall to still accept, 0–60.",
                                        "example": 2
                                    }
                                },
                                "required": [
                                    "amount",
                                    "pay_currency"
                                ]
                            },
                            "example": {
                                "amount": 25,
                                "currency": "USD",
                                "pay_currency": "USDT",
                                "network": "TRC20",
                                "order_id": "ORDER-1044",
                                "callback_url": "https://example.com/hooks/runepay"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "track_id": "INV_7C3P8L2V5N",
                                        "amount": "25.00",
                                        "currency": "USD",
                                        "pay_amount": "24.995000",
                                        "pay_currency": "USDT",
                                        "network": "TRON",
                                        "network_id": "TRC20",
                                        "address": "TSkW4NMLLp5ZLbP2NC1Fv3n1RmghJ8UtwT",
                                        "memo": null,
                                        "rate": "1.0002",
                                        "qr_code": "https://rpay.gg/checkout/INV_7C3P8L2V5N/qr",
                                        "payment_url": "https://rpay.gg/invoice/INV_9F2K4M1Q7X",
                                        "callback_url": "https://example.com/hooks/runepay",
                                        "order_id": "ORDER-1044",
                                        "email": null,
                                        "fee_paid_by_payer": 0,
                                        "under_paid_coverage": "0",
                                        "expired_at": 1754096400,
                                        "date": 1754092800
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 201,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "The key does not accept that coin or network. The message names which was requested.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation — commonly a missing `pay_currency`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/{track_id}": {
            "get": {
                "operationId": "getPayment",
                "summary": "Full current state of one payment, including every transaction seen.",
                "description": "Returns the same object your callback receives, so you can write one handler for both. Use it to reconcile — after a missed callback, or when a customer asks where their payment is — rather than as a polling loop.\n\nA payment belonging to another merchant returns `404`, not `403`: the API does not reveal that an identifier exists.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "track_id",
                        "in": "path",
                        "required": true,
                        "description": "The identifier returned at creation.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "INV_9F2K4M1Q7X"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "type": "invoice",
                                        "track_id": "INV_9F2K4M1Q7X",
                                        "status": "Paid",
                                        "amount": "25.00",
                                        "currency": "USD",
                                        "pay_amount": "24.995000",
                                        "pay_currency": "USDT",
                                        "network": "TRC20",
                                        "address": "TSkW4NMLLp5ZLbP2NC1Fv3n1RmghJ8UtwT",
                                        "received_amount": "24.995000",
                                        "rate": "1.0002",
                                        "order_id": "ORDER-1043",
                                        "email": "buyer@example.com",
                                        "description": "Rune verification — 1 year",
                                        "fee_paid_by_payer": 0,
                                        "under_paid_coverage": "0",
                                        "txs": [
                                            {
                                                "tx_hash": "9f2c…a41b",
                                                "amount": "24.995000",
                                                "currency": "USDT",
                                                "network": "TRC20",
                                                "confirmations": 20,
                                                "required_confirmations": 20,
                                                "status": "confirmed",
                                                "received_at": 1754093100
                                            }
                                        ],
                                        "date": 1754092800,
                                        "paid_at": 1754093100
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such payment on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment": {
            "get": {
                "operationId": "listPayments",
                "summary": "Paginated payment history with filters.",
                "description": "Newest first. Combine filters freely — they AND together. Intended for reconciliation and reporting; for live status use callbacks.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "size",
                        "in": "query",
                        "description": "Results per page, 1–200. Default 25. Values outside the range are clamped, not rejected.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "50"
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number, starting at 1.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1"
                    },
                    {
                        "name": "order_id",
                        "in": "query",
                        "description": "Exact match on your reference.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "ORDER-1043"
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "description": "Filter by kind: `invoice`, `white_label` or `static_address`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "invoice"
                    },
                    {
                        "name": "currency",
                        "in": "query",
                        "description": "Filter by the crypto paid in, e.g. `USDT`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "USDT"
                    },
                    {
                        "name": "from_date",
                        "in": "query",
                        "description": "Unix seconds. Only payments created at or after this.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1754006400"
                    },
                    {
                        "name": "to_date",
                        "in": "query",
                        "description": "Unix seconds. Only payments created at or before this.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1754092800"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "list": [
                                            "…payment objects, as returned by Retrieve a payment…"
                                        ],
                                        "meta": {
                                            "page": 1,
                                            "size": 25,
                                            "total": 143,
                                            "pages": 6
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/statistics": {
            "get": {
                "operationId": "getStatistics",
                "summary": "Counts, volume and conversion over a window.",
                "description": "Aggregates your payments so a dashboard does not have to page the whole history and add it up itself. Defaults to the last thirty days.\n\n**Volume counts confirmed payments only.** Including money that has been promised but not confirmed is how a dashboard ends up flattering the merchant, and the figure would move backwards whenever something expired.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "from_date",
                        "in": "query",
                        "description": "Unix seconds. Defaults to thirty days ago.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1754006400"
                    },
                    {
                        "name": "to_date",
                        "in": "query",
                        "description": "Unix seconds. Defaults to now.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1754092800"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "from_date": 1751500800,
                                        "to_date": 1754092800,
                                        "total": 143,
                                        "counts": {
                                            "paid": 118,
                                            "waiting": 4,
                                            "confirming": 2,
                                            "underpaid": 1,
                                            "expired": 16,
                                            "cancelled": 2,
                                            "failed": 0
                                        },
                                        "volume": "38207.85",
                                        "conversion_rate": 86.76,
                                        "by_currency": {
                                            "USDT": {
                                                "count": 96,
                                                "volume": "29180.40"
                                            },
                                            "BTC": {
                                                "count": 22,
                                                "volume": "9027.45"
                                            }
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/{track_id}/cancel": {
            "post": {
                "operationId": "cancelPayment",
                "summary": "Closes an unpaid payment so it stops accepting funds.",
                "description": "Only a payment that has not yet received money can be cancelled. Once funds are on the way — even unconfirmed — the payment is in a final state and this returns `409`, because the coins are real and cannot be un-sent.\n\nCancelling is optional: a payment expires on its own at `expired_at`. Cancel explicitly when the customer abandons checkout, so your dashboard stays clean.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "track_id",
                        "in": "path",
                        "required": true,
                        "description": "The payment to cancel.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "INV_9F2K4M1Q7X"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": [
                                        "…the updated payment object, with status \"Cancelled\"…"
                                    ],
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such payment on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The payment is paid, expired or already cancelled.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/balance": {
            "get": {
                "operationId": "getMerchantBalance",
                "summary": "What Rune Pay holds for you, per currency.",
                "description": "The same figures as the payout balance, but reachable with a MERCHANT key.\n\nThat distinction is the point: a merchant who only takes payments can hold no payout key at all — the credential that could move money out — and still see what they have. Reading a balance is not spending it.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "USDT": {
                                            "available": "4210.55000000",
                                            "locked": "100.00000000"
                                        },
                                        "BTC": {
                                            "available": "0.04120000",
                                            "locked": "0.00000000"
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The custodial wallet is disabled, so Rune Pay holds nothing to report.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/static-address": {
            "post": {
                "operationId": "createStaticAddress",
                "summary": "A permanent address per customer that credits you whatever arrives, whenever it arrives.",
                "description": "Unlike an invoice, a static address has no amount and no expiry. Anything sent to it is credited (minus your key's payment fee) and reported by callback. This is how you build user-balance top-ups: mint one address per user, store it, and let them fund it repeatedly.\n\n**The `order_id` is the identity.** Calling again with the same `order_id` and network returns the **same** address with a `200` — retries are free and safe. A different `order_id` mints a **new** address with a `201`. Omitting it entirely gives you one standing address per network. So for a platform with many users, pass each user's ID as `order_id` and every user gets an address of their own.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "network": {
                                        "type": "string",
                                        "description": "Which network to derive on, e.g. `TRC20`. Must be enabled and accepted by the key.",
                                        "example": "TRC20"
                                    },
                                    "callback_url": {
                                        "type": "string",
                                        "description": "Where to POST each incoming payment.",
                                        "example": "https://example.com/hooks/topup"
                                    },
                                    "order_id": {
                                        "type": "string",
                                        "description": "Your reference, and the reuse key — typically your user's ID. Same reference, same address; new reference, new address. Omitted means one shared standing address per network.",
                                        "example": "user-8842"
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Associated email.",
                                        "example": "user@example.com"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Free-text label.",
                                        "example": "Balance top-up"
                                    },
                                    "to_currency": {
                                        "type": "string",
                                        "description": "Auto-convert arrivals to this currency, priced at NEAR Intents rather than a market feed.",
                                        "example": "USDT"
                                    }
                                },
                                "required": [
                                    "network"
                                ]
                            },
                            "example": {
                                "network": "TRC20",
                                "order_id": "user-8842",
                                "callback_url": "https://example.com/hooks/topup",
                                "description": "Balance top-up"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "track_id": "SA_K3M9P2X7Q4L8VZ",
                                        "network": "TRON",
                                        "network_id": "TRC20",
                                        "currency": "USDT",
                                        "address": "TQ5nT8vRvZ2xKpL9mWc4bHfJ7dYaE1sGu3",
                                        "memo": null,
                                        "callback_url": "https://example.com/hooks/topup",
                                        "order_id": "user-8842",
                                        "email": null,
                                        "description": "Balance top-up",
                                        "status": "active",
                                        "date": 1754092800
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 201,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "The network is not available on this API key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The custodial wallet is disabled. Static addresses require Rune Pay to derive and watch the address itself.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The network is not in the enabled catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "The account is at its static-address cap (10,000 by default). Revoke unused addresses or contact support to raise it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Address derivation failed. The message carries the reason; nothing is stored.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    }
                }
            },
            "get": {
                "operationId": "listStaticAddresses",
                "summary": "Your static addresses, newest first, up to 200.",
                "description": "Includes revoked ones, so check `status`. There is no pagination here — the result is capped at 200; keep your own mapping of user to address rather than searching this list at runtime.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "list": [
                                            "…static address objects…"
                                        ]
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payment/static-address/{track_id}/revoke": {
            "post": {
                "operationId": "revokeStaticAddress",
                "summary": "Stops an address from being monitored.",
                "description": "Marks it `revoked` and stops watching it.\n\nThe address still exists on the blockchain and anyone who kept it can still send to it. Those funds will **not** be credited or reported. Stop showing a revoked address to customers before you revoke it, not after.",
                "tags": [
                    "Payments"
                ],
                "security": [
                    {
                        "merchantKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "track_id",
                        "in": "path",
                        "required": true,
                        "description": "The static address identifier.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "SA_K3M9P2X7Q4L8VZ"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "track_id": "SA_K3M9P2X7Q4L8VZ",
                                        "status": "revoked"
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such static address on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payout/balance": {
            "get": {
                "operationId": "getBalance",
                "summary": "Your balance per currency, split into available and locked.",
                "description": "`available` is what you can pay out right now. `locked` is reserved by payouts already queued or awaiting approval — it is still yours, but already committed. Check `available` before queueing a payout, not the sum.",
                "tags": [
                    "Payouts"
                ],
                "security": [
                    {
                        "payoutKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "USDT": {
                                            "available": "4210.55000000",
                                            "locked": "100.00000000"
                                        },
                                        "BTC": {
                                            "available": "0.04120000",
                                            "locked": "0.00000000"
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payout": {
            "post": {
                "operationId": "createPayout",
                "summary": "Queues an on-chain transfer from your balance.",
                "description": "The funds are locked immediately and the payout enters the same pipeline as a dashboard withdrawal — including approval, if your account requires it. This queues a payout; it does not bypass any control.\n\n**The destination address is not recoverable if wrong.** Rune Pay validates the format for the network, but cannot know whether the address is the one you meant. Validate against your own records before calling.",
                "tags": [
                    "Payouts"
                ],
                "security": [
                    {
                        "payoutKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "address": {
                                        "type": "string",
                                        "description": "Destination address. 20–120 characters, validated for the network.",
                                        "example": "TSkW4NMLLp5ZLbP2NC1Fv3n1RmghJ8UtwT"
                                    },
                                    "currency": {
                                        "type": "string",
                                        "description": "Currency to send, e.g. `USDT`.",
                                        "example": "USDT"
                                    },
                                    "amount": {
                                        "type": "number",
                                        "description": "Amount to send, before fees. Must exceed the network minimum.",
                                        "example": 100
                                    },
                                    "network": {
                                        "type": "string",
                                        "description": "Which network, when the coin exists on several. Strongly recommended — sending USDT to a TRON address over ERC20 loses the funds.",
                                        "example": "TRC20"
                                    },
                                    "order_id": {
                                        "type": "string",
                                        "description": "Idempotency key. Repeating a request with the same value returns the original payout instead of sending twice.",
                                        "example": "PAYOUT-556"
                                    },
                                    "callback_url": {
                                        "type": "string",
                                        "description": "Where to POST payout status changes.",
                                        "example": "https://example.com/hooks/payout"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Internal note, echoed in callbacks.",
                                        "example": "Affiliate payout May"
                                    }
                                },
                                "required": [
                                    "address",
                                    "currency",
                                    "amount"
                                ]
                            },
                            "example": {
                                "address": "TSkW4NMLLp5ZLbP2NC1Fv3n1RmghJ8UtwT",
                                "currency": "USDT",
                                "network": "TRC20",
                                "amount": 100,
                                "order_id": "PAYOUT-556",
                                "callback_url": "https://example.com/hooks/payout"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "track_id": "WD_4X8N2K9P5M",
                                        "status": "Processing",
                                        "internal_status": "awaiting_approval",
                                        "amount": "100.00000000",
                                        "currency": "USDT",
                                        "network": "TRON",
                                        "address": "TSkW4NMLLp5ZLbP2NC1Fv3n1RmghJ8UtwT",
                                        "tx_hash": null,
                                        "fee": "1.00000000",
                                        "net_amount": "99.00000000",
                                        "error": null,
                                        "date": 1754092800
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 201,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Insufficient available balance, amount below the minimum, invalid address for the network, or no available network for that currency.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The custodial wallet is disabled. In gateway mode funds settle straight to your own wallet, so there is no balance to pay out from.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A field failed validation.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "get": {
                "operationId": "listPayouts",
                "summary": "Paginated payout history with filters.",
                "description": "Newest first. Same pagination shape as the payment list.",
                "tags": [
                    "Payouts"
                ],
                "security": [
                    {
                        "payoutKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "size",
                        "in": "query",
                        "description": "Results per page, 1–200. Default 25.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "50"
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number, starting at 1.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1"
                    },
                    {
                        "name": "currency",
                        "in": "query",
                        "description": "Filter by currency.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "USDT"
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Filter by internal status, e.g. `sent`, `confirmed`, `rejected`.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "confirmed"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": {
                                        "list": [
                                            "…payout objects…"
                                        ],
                                        "meta": {
                                            "page": 1,
                                            "size": 25,
                                            "total": 38,
                                            "pages": 2
                                        }
                                    },
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/payout/{track_id}": {
            "get": {
                "operationId": "getPayout",
                "summary": "Current state of one payout.",
                "description": "Watch `tx_hash` to appear once broadcast, and `status` to reach `Confirmed`. On failure, `error` carries the reason — a rejection note from an approver, or the broadcast error.",
                "tags": [
                    "Payouts"
                ],
                "security": [
                    {
                        "payoutKey": []
                    },
                    {
                        "bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "track_id",
                        "in": "path",
                        "required": true,
                        "description": "The payout identifier.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "WD_4X8N2K9P5M"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object"
                                                }
                                            }
                                        }
                                    ]
                                },
                                "example": {
                                    "data": [
                                        "…the payout object, as returned at creation…"
                                    ],
                                    "message": "Operation completed successfully",
                                    "error": null,
                                    "status": 200,
                                    "version": "1.0"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such payout on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        }
    },
    "webhooks": {
        "paymentStatusChanged": {
            "post": {
                "operationId": "paymentCallback",
                "summary": "Payment status changed",
                "description": "When a payment or payout changes state, Rune Pay POSTs the full object to your `callback_url`. This is the intended way to learn about payments — it is immediate, and it costs you no rate limit.\n\n### Signature\n\nThe signing secret is the **SHA-256 hex digest of your API key** — not the key itself. Rune Pay stores only that digest, so it can sign with a value it holds while the raw key stays exclusively yours. Compute it once and store it in your environment: `echo -n \"rp_sec_YOUR_KEY\" | sha256sum`.\n\nVerify against the **raw request body**, before any JSON parsing. Re-encoding the parsed object produces different bytes — different key order, different spacing — and the signature will never match. Compare with a constant-time function: `==` on strings leaks timing information that can be used to forge a signature byte by byte.\n\n### Retries\n\nA failed delivery is retried five times with growing delays: **1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours**. After the sixth total attempt the callback is marked exhausted and no further attempt is made — reconcile with `GET /payment` if you suspect you missed one.\n\nCallbacks may arrive more than once for the same state — a retry after your server accepted but timed out, for example. Make your handler idempotent: key on `track_id` and ignore a status you have already processed. Delivering an order twice is worse than delivering it late.",
                "parameters": [
                    {
                        "name": "HMAC",
                        "in": "header",
                        "required": true,
                        "description": "Hex HMAC-SHA512 of the raw body, keyed with the SHA-256 digest of your API key.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Payment"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Acknowledged. Any 2xx stops the retries."
                    }
                }
            }
        },
        "payoutStatusChanged": {
            "post": {
                "operationId": "payoutCallback",
                "summary": "Payout status changed",
                "description": "Sent when a payout is broadcast, confirmed or fails. Signed identically to a payment callback.",
                "parameters": [
                    {
                        "name": "HMAC",
                        "in": "header",
                        "required": true,
                        "description": "Hex HMAC-SHA512 of the raw body.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Payout"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Acknowledged."
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "merchantKey": {
                "type": "apiKey",
                "in": "header",
                "name": "merchant_api_key",
                "description": "Merchant key (`rp_sec_…`). Grants the payment endpoints."
            },
            "payoutKey": {
                "type": "apiKey",
                "in": "header",
                "name": "payout_api_key",
                "description": "Payout key (`rp_out_…`). Grants the payout endpoints."
            },
            "bearer": {
                "type": "http",
                "scheme": "bearer",
                "description": "Either key may also be sent as `Authorization: Bearer …`."
            }
        },
        "schemas": {
            "Envelope": {
                "type": "object",
                "description": "Wraps every response, successful or not.",
                "required": [
                    "data",
                    "message",
                    "error",
                    "status",
                    "version"
                ],
                "properties": {
                    "data": {
                        "description": "The result, or null on failure."
                    },
                    "message": {
                        "type": "string"
                    },
                    "error": {
                        "oneOf": [
                            {
                                "type": "null"
                            },
                            {
                                "$ref": "#/components/schemas/ErrorDetail"
                            }
                        ]
                    },
                    "status": {
                        "type": "integer"
                    },
                    "version": {
                        "type": "string"
                    }
                }
            },
            "ErrorDetail": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "auth",
                            "request",
                            "server"
                        ]
                    },
                    "message": {
                        "type": "string"
                    },
                    "fields": {
                        "type": "object",
                        "description": "Present on 422 only: field name to list of problems.",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    "retry_after": {
                        "type": "integer",
                        "description": "Present on 429: seconds to wait."
                    }
                }
            },
            "Error": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "null"
                            },
                            "error": {
                                "$ref": "#/components/schemas/ErrorDetail"
                            }
                        }
                    }
                ]
            },
            "Payment": {
                "type": "object",
                "description": "The payment object, as returned by the API and sent in callbacks.",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "invoice",
                            "white_label",
                            "static_address"
                        ]
                    },
                    "track_id": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "Waiting",
                            "Underpaid",
                            "Confirming",
                            "Paid",
                            "Expired",
                            "Cancelled",
                            "Failed"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "currency": {
                        "type": "string"
                    },
                    "pay_amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "pay_currency": {
                        "type": "string"
                    },
                    "network": {
                        "type": "string"
                    },
                    "address": {
                        "type": "string"
                    },
                    "received_amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "rate": {
                        "type": "string",
                        "description": "Rate locked at creation."
                    },
                    "order_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "fee_paid_by_payer": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ]
                    },
                    "under_paid_coverage": {
                        "type": "string"
                    },
                    "txs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Transaction"
                        }
                    },
                    "date": {
                        "type": "integer",
                        "description": "Unix seconds."
                    },
                    "paid_at": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    }
                }
            },
            "Transaction": {
                "type": "object",
                "properties": {
                    "tx_hash": {
                        "type": "string"
                    },
                    "amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "currency": {
                        "type": "string"
                    },
                    "network": {
                        "type": "string"
                    },
                    "confirmations": {
                        "type": "integer"
                    },
                    "required_confirmations": {
                        "type": "integer"
                    },
                    "status": {
                        "type": "string"
                    },
                    "received_at": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    }
                }
            },
            "Payout": {
                "type": "object",
                "properties": {
                    "track_id": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "Processing",
                            "Confirming",
                            "Confirmed",
                            "Failed"
                        ]
                    },
                    "internal_status": {
                        "type": "string"
                    },
                    "amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "currency": {
                        "type": "string"
                    },
                    "network": {
                        "type": "string"
                    },
                    "address": {
                        "type": "string"
                    },
                    "tx_hash": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "fee": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "net_amount": {
                        "type": "string",
                        "description": "Decimal string. Never parse as a float."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "date": {
                        "type": "integer"
                    }
                }
            }
        },
        "responses": {
            "Unauthorized": {
                "description": "Missing, malformed, revoked or unknown API key.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Rate limit exceeded. Wait `error.retry_after` seconds.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            }
        }
    }
}