{
  "openapi": "3.1.0",
  "info": {
    "title": "Finscale Gateway API",
    "version": "v1",
    "summary": "One REST API for payments across many providers — smart routing, automatic failover, 40+ payment methods.",
    "description": "The Finscale Gateway API lets you accept payments through one integration while Finscale routes each transaction across multiple payment providers. Providers are opaque `prov_*` identifiers — you never integrate them directly.\n\n```text\nBase URL   https://api.finscale.dev/v1\nFormat     JSON request and response bodies, UTF-8\nTransport  TLS only — plain HTTP is rejected\n```\n\n## Authentication\n\nAuthenticate every request with your **secret key** as a Bearer token:\n\n```text\nAuthorization: Bearer sk_test_51FinscaleDemo…\n```\n\nSecret keys (`sk_test_…`, `sk_live_••••••••••••`) are server-side only — never ship them in client code. Publishable keys (`pk_test_…`) are used solely by hosted checkout. See [Authentication](https://docs.finscale.dev/authentication/).\n\n## Versioning\n\nThe API is versioned. Pin a version per request with the optional `Finscale-Version: v1` header; otherwise your account default applies. Breaking changes only ship in new versions.\n\n## Money\n\nAmounts are always **integers in minor units** with an uppercase ISO 4217 currency: `\"amount\": 4900, \"currency\": \"EUR\"` is €49.00. No floats, ever.\n\n## Idempotency\n\nSend an `Idempotency-Key` header (≤ 255 chars) on every POST. Replays within 24 hours return the original response; the same key with a different payload returns a `409 idempotency_error`. See [Idempotency](https://docs.finscale.dev/idempotency/).\n\n## Pagination\n\nList endpoints are cursor-paginated: `?limit=20&starting_after=pay_8Q2mX4nT1cVb`. Responses use the list envelope `{ \"object\": \"list\", \"data\": [...], \"has_more\": true }`. See [Pagination](https://docs.finscale.dev/pagination/).\n\n## Errors\n\nErrors use conventional HTTP status codes and a single envelope — `error.type` is one of `invalid_request_error` (400/404), `authentication_error` (401), `card_error` (402), `idempotency_error` (409), `rate_limit_error` (429), `api_error` (5xx). Every response carries a `request_id` (`req_…`) — include it when contacting support. See [Errors](https://docs.finscale.dev/errors/).\n\n## Test mode\n\nTest keys (`sk_test_…`) hit the same API against simulated providers. Test cards: `4242 4242 4242 4242` succeeds, `4000 0000 0000 0002` → `card_declined`, `4000 0000 0000 9995` → `insufficient_funds`. The magic amount `4999` forces a first-provider timeout so you can watch automatic failover in the `provider_attempts` array; `4002` fails with `failure_code: card_declined` — a final decline that is never retried; `4991` holds the payment in risk review (`risk.decision: \"review\"`, status `processing`); `4992` is blocked by risk screening (`failed` with `failure_code: payment_blocked`). See [Testing](https://docs.finscale.dev/testing/).\n\n## Webhooks\n\nFinscale signs every webhook delivery with `Finscale-Signature: t=<unix>,v1=<hmac-sha256 hex of \"t.body\">` using your endpoint's `whsec_…` secret. Deliveries retry with exponential backoff for 72 hours — respond 2xx fast and do the work async. See [Webhooks](https://docs.finscale.dev/concepts/webhooks/).\n\n## Rate limits\n\nDefault limit: 100 requests/second per account, burst-tolerant. Above it you receive `429 rate_limit_error` with a `Retry-After` header. Back off exponentially and retry idempotently.",
    "contact": {
      "name": "Finscale",
      "url": "https://finscale.dev"
    },
    "x-logo": {
      "url": "/assets/logo.svg",
      "altText": "Finscale"
    }
  },
  "servers": [
    {
      "url": "https://api.finscale.dev/v1",
      "description": "Production and test mode — the key you use (sk_live_… / sk_test_…) selects the mode."
    }
  ],
  "security": [
    {
      "secret_key": []
    }
  ],
  "tags": [
    {
      "name": "Payments",
      "description": "A Payment is one attempt to collect money from a customer. Finscale routes it across providers per your routing rules and retries failures automatically — the full story lives in `provider_attempts`."
    },
    {
      "name": "Refunds",
      "description": "Return some or all of a payment to the customer. Refunds are routed to the provider that processed the original payment — you never track which one that was."
    },
    {
      "name": "Disputes",
      "description": "Chargebacks — customers formally contesting payments through their bank or card network, normalized across schemes. Respond with evidence or accept before the deadline; disputes escalate chargeback → pre-arbitration → arbitration."
    },
    {
      "name": "Customers",
      "description": "A Customer groups payments and saved payment methods under one identity."
    },
    {
      "name": "Payment Methods",
      "description": "Reusable payment instruments (cards, bank debits) attached to customers. Raw card numbers are accepted in test mode only — in live mode use hosted checkout so card data never touches your servers."
    },
    {
      "name": "Merchants",
      "description": "Sub-merchants you onboard for acquiring: legal identity, KYB verification status, and per-capability activation. A MID is assigned when a merchant becomes active."
    },
    {
      "name": "Payouts",
      "description": "Money Finscale pays out to your settlement bank account. Read-only."
    },
    {
      "name": "Settlement Reports",
      "description": "Daily per-provider reconciliation reports. Retrieve as JSON, or as CSV with `Accept: text/csv`."
    },
    {
      "name": "Events",
      "description": "An immutable log of everything that happened in your account. Webhook deliveries wrap these same Event objects."
    },
    {
      "name": "Webhook Endpoints",
      "description": "HTTPS URLs that receive signed Event deliveries. The signing secret is returned once, at creation."
    },
    {
      "name": "Routing Rules",
      "description": "Per-merchant rules that steer transactions to providers: prefer one, split by weight, or block. Lowest `priority` number wins; smart routing decides when no rule matches."
    },
    {
      "name": "Providers",
      "description": "The acquirers and PSPs behind Finscale, exposed as opaque `prov_*` ids with methods, regions, health status, and 7-day auth rate. Read-only."
    },
    {
      "name": "Balance",
      "description": "Your current available and pending balance per currency."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Core resources",
      "tags": [
        "Payments",
        "Refunds",
        "Disputes",
        "Customers",
        "Payment Methods",
        "Merchants"
      ]
    },
    {
      "name": "Money movement",
      "tags": [
        "Payouts",
        "Settlement Reports",
        "Balance"
      ]
    },
    {
      "name": "Platform",
      "tags": [
        "Events",
        "Webhook Endpoints",
        "Routing Rules",
        "Providers"
      ]
    }
  ],
  "paths": {
    "/payments": {
      "get": {
        "operationId": "listPayments",
        "tags": [
          "Payments"
        ],
        "summary": "List payments",
        "description": "Returns your payments, most recently created first. Filter by status, customer, reference, or creation time.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return payments with this status.",
            "schema": {
              "$ref": "#/components/schemas/PaymentStatus"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "description": "Only return payments for this customer id.",
            "schema": {
              "type": "string"
            },
            "example": "cus_4T8nQb2Wp1Zr"
          },
          {
            "name": "reference",
            "in": "query",
            "description": "Only return payments with this merchant reference.",
            "schema": {
              "type": "string"
            },
            "example": "ord_9f21_0716"
          },
          {
            "name": "created_gte",
            "in": "query",
            "description": "Only return payments created at or after this ISO 8601 timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_lte",
            "in": "query",
            "description": "Only return payments created at or before this ISO 8601 timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of payments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "pay_8Q2mX4nT1cVb",
                      "object": "payment",
                      "amount": 4900,
                      "amount_captured": 4900,
                      "amount_refunded": 0,
                      "currency": "EUR",
                      "status": "succeeded",
                      "payment_method": "ideal",
                      "payment_method_id": null,
                      "payment_method_details": {
                        "ideal": {
                          "bank": "demo_bank_nl",
                          "iban_last4": "3401"
                        }
                      },
                      "capture_method": "automatic",
                      "customer": "cus_4T8nQb2Wp1Zr",
                      "description": null,
                      "reference": "ord_9f21_0716",
                      "metadata": {},
                      "provider": "prov_eu_acq_02",
                      "provider_attempts": [
                        {
                          "provider": "prov_eu_acq_01",
                          "outcome": "timeout",
                          "decline_code": null,
                          "latency_ms": 8003,
                          "attempted_at": "2026-07-16T09:24:31Z"
                        },
                        {
                          "provider": "prov_eu_acq_02",
                          "outcome": "approved",
                          "decline_code": null,
                          "latency_ms": 942,
                          "attempted_at": "2026-07-16T09:24:40Z"
                        }
                      ],
                      "risk": null,
                      "next_action": null,
                      "return_url": "https://shop.example.com/checkout/return",
                      "refunded": false,
                      "partially_refunded": false,
                      "failure_code": null,
                      "failure_message": null,
                      "livemode": false,
                      "created_at": "2026-07-16T09:24:31Z"
                    }
                  ],
                  "has_more": true,
                  "url": "/v1/payments"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl \"https://api.finscale.dev/v1/payments?limit=20&status=succeeded\" \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "let url = \"https://api.finscale.dev/v1/payments?limit=20&status=succeeded\";\nwhile (url) {\n  const res = await fetch(url, {\n    headers: { \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\" }\n  });\n  const page = await res.json();\n  for (const payment of page.data) process(payment);\n  url = page.has_more\n    ? `https://api.finscale.dev/v1/payments?limit=20&status=succeeded&starting_after=${page.data.at(-1).id}`\n    : null;\n}"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nparams = {\"limit\": 20, \"status\": \"succeeded\"}\nwhile True:\n    page = requests.get(\n        \"https://api.finscale.dev/v1/payments\",\n        headers={\"Authorization\": \"Bearer sk_test_51FinscaleDemo…\"},\n        params=params,\n    ).json()\n    for payment in page[\"data\"]:\n        process(payment)\n    if not page[\"has_more\"]:\n        break\n    params[\"starting_after\"] = page[\"data\"][-1][\"id\"]"
          }
        ]
      },
      "post": {
        "operationId": "createPayment",
        "tags": [
          "Payments"
        ],
        "summary": "Create a payment",
        "description": "Creates a payment for the given amount and method, then routes it. Smart routing scores every eligible provider on cost, 7-day auth rate, currency, and method — your [routing rules](https://docs.finscale.dev/concepts/routing/) override it. If the first provider declines or times out, Finscale retries on the next one automatically; every attempt is recorded in `provider_attempts`.\n\nRedirect methods — bank redirects (iDEAL, Bancontact, FPX, …), real-time rails (UPI, PIX, Blik, PayNow, PromptPay, …), app wallets (PayPal, Alipay, WeChat Pay, …), buy now pay later (Klarna, Affirm, Afterpay / Clearpay), and vouchers (OXXO, Boleto, Konbini, Multibanco) — return `status: requires_action` with a `next_action.url` to send the customer to. Card payments with `capture_method: manual` authorize first and wait in `requires_capture`.\n\nAlways send an `Idempotency-Key` — network retries then can never double-charge. In test mode, `\"amount\": 4999` forces a first-provider timeout so you can watch failover happen; `4002` fails with `failure_code: card_declined` (a final decline, never retried); `4991` forces a risk-review hold and `4992` a risk block.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentRequest"
              },
              "examples": {
                "ideal": {
                  "summary": "iDEAL — bank redirect",
                  "value": {
                    "amount": 4900,
                    "currency": "EUR",
                    "payment_method": "ideal",
                    "reference": "ord_9f21_0716",
                    "customer": {
                      "email": "anna@example.com"
                    },
                    "return_url": "https://shop.example.com/checkout/return"
                  }
                },
                "upi": {
                  "summary": "UPI — real-time, collect VPA on the hosted page",
                  "value": {
                    "amount": 419900,
                    "currency": "INR",
                    "payment_method": "upi",
                    "reference": "ord_9f21_0716",
                    "customer": {
                      "email": "anna@example.com"
                    },
                    "return_url": "https://shop.example.com/checkout/return"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The payment was created and routed. Both examples wait in `requires_action`: send the customer to `next_action.url` — the hosted page runs the method's flow (bank selection for iDEAL, VPA collection and in-app approval for UPI).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "examples": {
                  "ideal": {
                    "summary": "iDEAL — routed, awaiting redirect",
                    "value": {
                      "id": "pay_8Q2mX4nT1cVb",
                      "object": "payment",
                      "amount": 4900,
                      "amount_captured": 0,
                      "amount_refunded": 0,
                      "currency": "EUR",
                      "status": "requires_action",
                      "payment_method": "ideal",
                      "payment_method_id": null,
                      "payment_method_details": null,
                      "capture_method": "automatic",
                      "customer": "cus_4T8nQb2Wp1Zr",
                      "description": null,
                      "reference": "ord_9f21_0716",
                      "metadata": {},
                      "provider": "prov_eu_acq_01",
                      "provider_attempts": [
                        {
                          "provider": "prov_eu_acq_01",
                          "outcome": "pending",
                          "decline_code": null,
                          "latency_ms": null,
                          "attempted_at": "2026-07-16T09:24:31Z"
                        }
                      ],
                      "risk": null,
                      "next_action": {
                        "type": "redirect",
                        "url": "https://pay.finscale.dev/r/8Q2mX4nT"
                      },
                      "return_url": "https://shop.example.com/checkout/return",
                      "refunded": false,
                      "partially_refunded": false,
                      "failure_code": null,
                      "failure_message": null,
                      "livemode": false,
                      "created_at": "2026-07-16T09:24:31Z"
                    }
                  },
                  "upi": {
                    "summary": "UPI — routed, awaiting VPA approval",
                    "value": {
                      "id": "pay_7Nu4pV2rK9Wd",
                      "object": "payment",
                      "amount": 419900,
                      "amount_captured": 0,
                      "amount_refunded": 0,
                      "currency": "INR",
                      "status": "requires_action",
                      "payment_method": "upi",
                      "payment_method_id": null,
                      "payment_method_details": null,
                      "capture_method": "automatic",
                      "customer": "cus_4T8nQb2Wp1Zr",
                      "description": null,
                      "reference": "ord_9f21_0716",
                      "metadata": {},
                      "provider": "prov_in_psp_01",
                      "provider_attempts": [
                        {
                          "provider": "prov_in_psp_01",
                          "outcome": "pending",
                          "decline_code": null,
                          "latency_ms": null,
                          "attempted_at": "2026-07-16T09:24:31Z"
                        }
                      ],
                      "risk": null,
                      "next_action": {
                        "type": "redirect",
                        "url": "https://pay.finscale.dev/r/7Nu4pV2r"
                      },
                      "return_url": "https://shop.example.com/checkout/return",
                      "refunded": false,
                      "partially_refunded": false,
                      "failure_code": null,
                      "failure_message": null,
                      "livemode": false,
                      "created_at": "2026-07-16T09:24:31Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentDeclined"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://api.finscale.dev/v1/payments \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\" \\\n  -H \"Idempotency-Key: idem_ord_9f21_0716\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"amount\": 4900,\n    \"currency\": \"EUR\",\n    \"payment_method\": \"ideal\",\n    \"reference\": \"ord_9f21_0716\",\n    \"customer\": { \"email\": \"anna@example.com\" },\n    \"return_url\": \"https://shop.example.com/checkout/return\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch(\"https://api.finscale.dev/v1/payments\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n    \"Idempotency-Key\": \"idem_ord_9f21_0716\",\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({\n    amount: 4900,\n    currency: \"EUR\",\n    payment_method: \"ideal\",\n    reference: \"ord_9f21_0716\",\n    customer: { email: \"anna@example.com\" },\n    return_url: \"https://shop.example.com/checkout/return\"\n  })\n});\nconst payment = await res.json();\n// payment.status === \"requires_action\" → redirect to payment.next_action.url"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nres = requests.post(\n    \"https://api.finscale.dev/v1/payments\",\n    headers={\n        \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n        \"Idempotency-Key\": \"idem_ord_9f21_0716\",\n    },\n    json={\n        \"amount\": 4900,\n        \"currency\": \"EUR\",\n        \"payment_method\": \"ideal\",\n        \"reference\": \"ord_9f21_0716\",\n        \"customer\": {\"email\": \"anna@example.com\"},\n        \"return_url\": \"https://shop.example.com/checkout/return\",\n    },\n)\npayment = res.json()\n# payment[\"status\"] == \"requires_action\" -> redirect to payment[\"next_action\"][\"url\"]"
          }
        ]
      }
    },
    "/payments/{id}": {
      "get": {
        "operationId": "retrievePayment",
        "tags": [
          "Payments"
        ],
        "summary": "Retrieve a payment",
        "description": "Returns the payment with the given id, including the full `provider_attempts` history. This example shows the canonical failover: attempt 1 on `prov_eu_acq_01` timed out, the retry on `prov_eu_acq_02` was approved — one API call, two attempts, zero merchant code.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment id, prefixed `pay_`.",
            "schema": {
              "type": "string"
            },
            "example": "pay_8Q2mX4nT1cVb"
          }
        ],
        "responses": {
          "200": {
            "description": "The payment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "example": {
                  "id": "pay_8Q2mX4nT1cVb",
                  "object": "payment",
                  "amount": 4900,
                  "amount_captured": 4900,
                  "amount_refunded": 0,
                  "currency": "EUR",
                  "status": "succeeded",
                  "payment_method": "ideal",
                  "payment_method_id": null,
                  "payment_method_details": {
                    "ideal": {
                      "bank": "demo_bank_nl",
                      "iban_last4": "3401"
                    }
                  },
                  "capture_method": "automatic",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "description": null,
                  "reference": "ord_9f21_0716",
                  "metadata": {},
                  "provider": "prov_eu_acq_02",
                  "provider_attempts": [
                    {
                      "provider": "prov_eu_acq_01",
                      "outcome": "timeout",
                      "decline_code": null,
                      "latency_ms": 8003,
                      "attempted_at": "2026-07-16T09:24:31Z"
                    },
                    {
                      "provider": "prov_eu_acq_02",
                      "outcome": "approved",
                      "decline_code": null,
                      "latency_ms": 942,
                      "attempted_at": "2026-07-16T09:24:40Z"
                    }
                  ],
                  "risk": null,
                  "next_action": null,
                  "return_url": "https://shop.example.com/checkout/return",
                  "refunded": false,
                  "partially_refunded": false,
                  "failure_code": null,
                  "failure_message": null,
                  "livemode": false,
                  "created_at": "2026-07-16T09:24:31Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://api.finscale.dev/v1/payments/pay_8Q2mX4nT1cVb \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch(\n  \"https://api.finscale.dev/v1/payments/pay_8Q2mX4nT1cVb\",\n  { headers: { \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\" } }\n);\nconst payment = await res.json();\nconsole.log(payment.status, payment.provider_attempts);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nres = requests.get(\n    \"https://api.finscale.dev/v1/payments/pay_8Q2mX4nT1cVb\",\n    headers={\"Authorization\": \"Bearer sk_test_51FinscaleDemo…\"},\n)\npayment = res.json()\nprint(payment[\"status\"], payment[\"provider_attempts\"])"
          }
        ]
      }
    },
    "/payments/{id}/confirm": {
      "post": {
        "operationId": "confirmPayment",
        "tags": [
          "Payments"
        ],
        "summary": "Confirm a payment",
        "description": "Confirms a payment created with `confirm: false`, moving it out of `requires_confirmation` and into routing. Use deferred confirmation when you build the payment early in your checkout and confirm once the customer hits *Pay*.\n\nOptionally switch the instrument at confirm time with `payment_method_id`. Confirming a payment in any state other than `requires_confirmation` returns a `400 invalid_request_error`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment id, prefixed `pay_`.",
            "schema": {
              "type": "string"
            },
            "example": "pay_8Q2mX4nT1cVb"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmPaymentRequest"
              },
              "example": {
                "payment_method_id": "pm_7Wq2xN9dT4Ls"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The confirmed payment, now routed — here waiting on the customer's redirect.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "example": {
                  "id": "pay_8Q2mX4nT1cVb",
                  "object": "payment",
                  "amount": 4900,
                  "amount_captured": 0,
                  "amount_refunded": 0,
                  "currency": "EUR",
                  "status": "requires_action",
                  "payment_method": "ideal",
                  "payment_method_id": null,
                  "payment_method_details": null,
                  "capture_method": "automatic",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "description": null,
                  "reference": "ord_9f21_0716",
                  "metadata": {},
                  "provider": "prov_eu_acq_01",
                  "provider_attempts": [
                    {
                      "provider": "prov_eu_acq_01",
                      "outcome": "pending",
                      "decline_code": null,
                      "latency_ms": null,
                      "attempted_at": "2026-07-16T09:24:31Z"
                    }
                  ],
                  "risk": null,
                  "next_action": {
                    "type": "redirect",
                    "url": "https://pay.finscale.dev/r/8Q2mX4nT"
                  },
                  "return_url": "https://shop.example.com/checkout/return",
                  "refunded": false,
                  "partially_refunded": false,
                  "failure_code": null,
                  "failure_message": null,
                  "livemode": false,
                  "created_at": "2026-07-16T09:24:31Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentDeclined"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payments/{id}/capture": {
      "post": {
        "operationId": "capturePayment",
        "tags": [
          "Payments"
        ],
        "summary": "Capture a payment",
        "description": "Captures the funds of a card payment authorized with `capture_method: manual` (status `requires_capture`).\n\nOmit `amount` to capture the remaining authorization in full. Pass a smaller `amount` for a **partial capture**. Where the card network supports **multiple capture**, a partial capture leaves the payment in `requires_capture` and you can call capture again until the authorization is drawn down — `amount_captured` accumulates across calls; on networks without multiple-capture support the un-captured remainder is released after the first capture. The payment reaches `succeeded` once the authorization closes with funds captured.\n\nUncaptured authorizations expire after 7 days and release automatically. Need to capture more than you authorized? Raise the authorization first with `POST /payments/{id}/increment_authorization`. Capturing a payment not in `requires_capture` returns a `400 invalid_request_error` with code `payment_not_capturable`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment id, prefixed `pay_`.",
            "schema": {
              "type": "string"
            },
            "example": "pay_2Xw9cJ6pF3Md"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CapturePaymentRequest"
              },
              "example": {
                "amount": 4900
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The captured payment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "example": {
                  "id": "pay_2Xw9cJ6pF3Md",
                  "object": "payment",
                  "amount": 4900,
                  "amount_captured": 4900,
                  "amount_refunded": 0,
                  "currency": "EUR",
                  "status": "succeeded",
                  "payment_method": "card",
                  "payment_method_id": "pm_7Wq2xN9dT4Ls",
                  "payment_method_details": {
                    "card": {
                      "brand": "visa",
                      "last4": "4242",
                      "exp_month": 12,
                      "exp_year": 2028,
                      "funding": "debit",
                      "country": "NL"
                    }
                  },
                  "capture_method": "manual",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "description": null,
                  "reference": "ord_9f21_0716",
                  "metadata": {},
                  "provider": "prov_eu_acq_01",
                  "provider_attempts": [
                    {
                      "provider": "prov_eu_acq_01",
                      "outcome": "approved",
                      "decline_code": null,
                      "latency_ms": 611,
                      "attempted_at": "2026-07-16T09:24:31Z"
                    }
                  ],
                  "risk": {
                    "score": 74,
                    "decision": "approved",
                    "checks": {
                      "avs_result": "pass",
                      "cvv_result": "pass"
                    }
                  },
                  "next_action": null,
                  "return_url": null,
                  "refunded": false,
                  "partially_refunded": false,
                  "failure_code": null,
                  "failure_message": null,
                  "livemode": false,
                  "created_at": "2026-07-16T09:24:31Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payments/{id}/increment_authorization": {
      "post": {
        "operationId": "incrementAuthorization",
        "tags": [
          "Payments"
        ],
        "summary": "Increment an authorization",
        "description": "Raises the authorized amount of a card payment waiting in `requires_capture` (`capture_method: manual`) — growing hotel folios, bar tabs, upsells — without asking the customer to pay again. `amount` is the **new total** authorization in minor units and must be greater than the current `amount`; the issuer approves the difference and the payment stays in `requires_capture`. You can increment multiple times before capturing.\n\nPre-authorizations only: on payments that are not `requires_capture`, or on card networks without incremental-authorization support, the call returns a `400 invalid_request_error` with code `payment_not_incrementable` and the original authorization is unaffected.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment id, prefixed `pay_`.",
            "schema": {
              "type": "string"
            },
            "example": "pay_2Xw9cJ6pF3Md"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IncrementAuthorizationRequest"
              },
              "example": {
                "amount": 6900
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The payment with the raised authorization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "example": {
                  "id": "pay_2Xw9cJ6pF3Md",
                  "object": "payment",
                  "amount": 6900,
                  "amount_captured": 0,
                  "amount_refunded": 0,
                  "currency": "EUR",
                  "status": "requires_capture",
                  "payment_method": "card",
                  "payment_method_id": "pm_7Wq2xN9dT4Ls",
                  "payment_method_details": {
                    "card": {
                      "brand": "visa",
                      "last4": "4242",
                      "exp_month": 12,
                      "exp_year": 2028,
                      "funding": "debit",
                      "country": "NL"
                    }
                  },
                  "capture_method": "manual",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "description": null,
                  "reference": "ord_9f21_0716",
                  "metadata": {},
                  "provider": "prov_eu_acq_01",
                  "provider_attempts": [
                    {
                      "provider": "prov_eu_acq_01",
                      "outcome": "approved",
                      "decline_code": null,
                      "latency_ms": 611,
                      "attempted_at": "2026-07-16T09:24:31Z"
                    }
                  ],
                  "risk": {
                    "score": 74,
                    "decision": "approved",
                    "checks": {
                      "avs_result": "pass",
                      "cvv_result": "pass"
                    }
                  },
                  "next_action": null,
                  "return_url": null,
                  "refunded": false,
                  "partially_refunded": false,
                  "failure_code": null,
                  "failure_message": null,
                  "livemode": false,
                  "created_at": "2026-07-16T09:24:31Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payments/{id}/cancel": {
      "post": {
        "operationId": "cancelPayment",
        "tags": [
          "Payments"
        ],
        "summary": "Cancel a payment",
        "description": "Cancels a payment in `requires_confirmation`, `requires_action`, or `requires_capture`. Canceling a `requires_capture` payment is a **void**: Finscale sends an authorization reversal to the provider, so the hold on the customer’s card is released immediately instead of expiring on its own days later. Payments that are `processing` or terminal cannot be canceled — refund a `succeeded` payment instead.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment id, prefixed `pay_`.",
            "schema": {
              "type": "string"
            },
            "example": "pay_8Q2mX4nT1cVb"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The canceled payment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "example": {
                  "id": "pay_8Q2mX4nT1cVb",
                  "object": "payment",
                  "amount": 4900,
                  "amount_captured": 0,
                  "amount_refunded": 0,
                  "currency": "EUR",
                  "status": "canceled",
                  "payment_method": "ideal",
                  "payment_method_id": null,
                  "payment_method_details": null,
                  "capture_method": "automatic",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "description": null,
                  "reference": "ord_9f21_0716",
                  "metadata": {},
                  "provider": null,
                  "provider_attempts": [],
                  "risk": null,
                  "next_action": null,
                  "return_url": "https://shop.example.com/checkout/return",
                  "refunded": false,
                  "partially_refunded": false,
                  "failure_code": null,
                  "failure_message": null,
                  "livemode": false,
                  "created_at": "2026-07-16T09:24:31Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/refunds": {
      "get": {
        "operationId": "listRefunds",
        "tags": [
          "Refunds"
        ],
        "summary": "List refunds",
        "description": "Returns your refunds, most recently created first. Filter by the original payment.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "payment",
            "in": "query",
            "description": "Only return refunds of this payment id.",
            "schema": {
              "type": "string"
            },
            "example": "pay_8Q2mX4nT1cVb"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of refunds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "rf_3Vp7dK2wQx",
                      "object": "refund",
                      "amount": 4900,
                      "currency": "EUR",
                      "payment": "pay_8Q2mX4nT1cVb",
                      "reason": "requested_by_customer",
                      "status": "pending",
                      "provider": "prov_eu_acq_02",
                      "failure_code": null,
                      "metadata": {},
                      "livemode": false,
                      "created_at": "2026-07-16T14:02:11Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/refunds"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createRefund",
        "tags": [
          "Refunds"
        ],
        "summary": "Create a refund",
        "description": "Refunds a succeeded payment, in part or in full. Finscale routes the refund to whichever provider processed the original payment — you don't need to know which one that was.\n\nOmit `amount` to refund the remaining un-refunded balance. Partial refunds pass `amount` in minor units; the sum of refunds can never exceed the captured amount. Refunds start `pending` and settle to `succeeded` or `failed` — subscribe to `refund.succeeded` / `refund.failed` webhooks rather than polling.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRefundRequest"
              },
              "example": {
                "payment": "pay_8Q2mX4nT1cVb",
                "reason": "requested_by_customer"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The refund, created in status `pending`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refund"
                },
                "example": {
                  "id": "rf_3Vp7dK2wQx",
                  "object": "refund",
                  "amount": 4900,
                  "currency": "EUR",
                  "payment": "pay_8Q2mX4nT1cVb",
                  "reason": "requested_by_customer",
                  "status": "pending",
                  "provider": "prov_eu_acq_02",
                  "failure_code": null,
                  "metadata": {},
                  "livemode": false,
                  "created_at": "2026-07-16T14:02:11Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://api.finscale.dev/v1/refunds \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\" \\\n  -H \"Idempotency-Key: idem_rf_ord_9f21_0716\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"payment\": \"pay_8Q2mX4nT1cVb\",\n    \"reason\": \"requested_by_customer\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch(\"https://api.finscale.dev/v1/refunds\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n    \"Idempotency-Key\": \"idem_rf_ord_9f21_0716\",\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({ payment: \"pay_8Q2mX4nT1cVb\", reason: \"requested_by_customer\" })\n});\nconst refund = await res.json();\n// Full refund of €49.00 — omit \"amount\" to refund the remaining balance"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nres = requests.post(\n    \"https://api.finscale.dev/v1/refunds\",\n    headers={\n        \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n        \"Idempotency-Key\": \"idem_rf_ord_9f21_0716\",\n    },\n    json={\"payment\": \"pay_8Q2mX4nT1cVb\", \"reason\": \"requested_by_customer\"},\n)\nrefund = res.json()\n# Full refund of €49.00 — omit \"amount\" to refund the remaining balance"
          }
        ]
      }
    },
    "/refunds/{id}": {
      "get": {
        "operationId": "retrieveRefund",
        "tags": [
          "Refunds"
        ],
        "summary": "Retrieve a refund",
        "description": "Returns the refund with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The refund id, prefixed `rf_`.",
            "schema": {
              "type": "string"
            },
            "example": "rf_3Vp7dK2wQx"
          }
        ],
        "responses": {
          "200": {
            "description": "The refund.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refund"
                },
                "example": {
                  "id": "rf_3Vp7dK2wQx",
                  "object": "refund",
                  "amount": 4900,
                  "currency": "EUR",
                  "payment": "pay_8Q2mX4nT1cVb",
                  "reason": "requested_by_customer",
                  "status": "pending",
                  "provider": "prov_eu_acq_02",
                  "failure_code": null,
                  "metadata": {},
                  "livemode": false,
                  "created_at": "2026-07-16T14:02:11Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/disputes": {
      "get": {
        "operationId": "listDisputes",
        "tags": [
          "Disputes"
        ],
        "summary": "List disputes",
        "description": "Returns your disputes, most recently created first. Filter by status or by the disputed payment.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return disputes with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "needs_response",
                "under_review",
                "won",
                "lost",
                "accepted"
              ]
            },
            "example": "needs_response"
          },
          {
            "name": "payment",
            "in": "query",
            "description": "Only return disputes of this payment id.",
            "schema": {
              "type": "string"
            },
            "example": "pay_3Vt7Kd9sLm2x"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of disputes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisputeList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "dp_5Kw2mR8vQz1N",
                      "object": "dispute",
                      "payment": "pay_3Vt7Kd9sLm2x",
                      "amount": 12900,
                      "currency": "EUR",
                      "reason": "fraudulent",
                      "stage": "chargeback",
                      "status": "needs_response",
                      "evidence_due_by": "2026-07-30T23:59:59Z",
                      "livemode": false,
                      "created_at": "2026-07-16T18:40:22Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/disputes"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/disputes/{id}": {
      "get": {
        "operationId": "retrieveDispute",
        "tags": [
          "Disputes"
        ],
        "summary": "Retrieve a dispute",
        "description": "Returns the dispute with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The dispute id, prefixed `dp_`.",
            "schema": {
              "type": "string"
            },
            "example": "dp_5Kw2mR8vQz1N"
          }
        ],
        "responses": {
          "200": {
            "description": "The dispute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dispute"
                },
                "example": {
                  "id": "dp_5Kw2mR8vQz1N",
                  "object": "dispute",
                  "payment": "pay_3Vt7Kd9sLm2x",
                  "amount": 12900,
                  "currency": "EUR",
                  "reason": "fraudulent",
                  "stage": "chargeback",
                  "status": "needs_response",
                  "evidence_due_by": "2026-07-30T23:59:59Z",
                  "livemode": false,
                  "created_at": "2026-07-16T18:40:22Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/disputes/{id}/accept": {
      "post": {
        "operationId": "acceptDispute",
        "tags": [
          "Disputes"
        ],
        "summary": "Accept a dispute",
        "description": "Accepts liability for the dispute: it moves to `accepted` (terminal) and the withheld funds go to the cardholder. This cannot be undone. Accepting is the right move when the dispute is legitimate — fighting and losing costs the same and takes longer.\n\nOnly disputes in `needs_response` can be accepted; anything else returns a `400 invalid_request_error` with code `dispute_not_actionable`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The dispute id, prefixed `dp_`.",
            "schema": {
              "type": "string"
            },
            "example": "dp_5Kw2mR8vQz1N"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The accepted dispute.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dispute"
                },
                "example": {
                  "id": "dp_5Kw2mR8vQz1N",
                  "object": "dispute",
                  "payment": "pay_3Vt7Kd9sLm2x",
                  "amount": 12900,
                  "currency": "EUR",
                  "reason": "fraudulent",
                  "stage": "chargeback",
                  "status": "accepted",
                  "evidence_due_by": null,
                  "livemode": false,
                  "created_at": "2026-07-16T18:40:22Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/disputes/{id}/evidence": {
      "post": {
        "operationId": "submitDisputeEvidence",
        "tags": [
          "Disputes"
        ],
        "summary": "Submit dispute evidence",
        "description": "Submits evidence to contest the dispute; it moves to `under_review` and Finscale forwards the package to the network in the format each scheme expects. Submit once and completely — most schemes allow a single evidence submission per stage.\n\n`fields` carries structured text evidence; `files` carries supporting documents as HTTPS URLs reachable by Finscale. Only disputes in `needs_response` accept evidence; anything else returns a `400 invalid_request_error` with code `dispute_not_actionable`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The dispute id, prefixed `dp_`.",
            "schema": {
              "type": "string"
            },
            "example": "dp_5Kw2mR8vQz1N"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitDisputeEvidenceRequest"
              },
              "example": {
                "fields": {
                  "product_description": "Wireless headphones, order ord_9f21_0716",
                  "tracking_number": "3SFINS0912837465",
                  "customer_communication": "Order confirmation and delivery notification, exported as PDF"
                },
                "files": [
                  "https://files.example.com/evidence/ord_9f21_0716-delivery.pdf"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The dispute, now under review.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dispute"
                },
                "example": {
                  "id": "dp_5Kw2mR8vQz1N",
                  "object": "dispute",
                  "payment": "pay_3Vt7Kd9sLm2x",
                  "amount": 12900,
                  "currency": "EUR",
                  "reason": "fraudulent",
                  "stage": "chargeback",
                  "status": "under_review",
                  "evidence_due_by": null,
                  "livemode": false,
                  "created_at": "2026-07-16T18:40:22Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/customers": {
      "get": {
        "operationId": "listCustomers",
        "tags": [
          "Customers"
        ],
        "summary": "List customers",
        "description": "Returns your customers, most recently created first. Filter by exact email.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "email",
            "in": "query",
            "description": "Only return customers with this exact email address.",
            "schema": {
              "type": "string",
              "format": "email"
            },
            "example": "anna@example.com"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of customers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "cus_4T8nQb2Wp1Zr",
                      "object": "customer",
                      "email": "anna@example.com",
                      "name": "Anna de Vries",
                      "phone": null,
                      "description": null,
                      "default_payment_method": null,
                      "metadata": {},
                      "livemode": false,
                      "created_at": "2026-07-16T09:20:04Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/customers"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createCustomer",
        "tags": [
          "Customers"
        ],
        "summary": "Create a customer",
        "description": "Creates a customer you can attach payments and payment methods to. You can also create customers implicitly by passing an inline `customer` object when creating a payment.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomerRequest"
              },
              "example": {
                "email": "anna@example.com",
                "name": "Anna de Vries"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The customer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                },
                "example": {
                  "id": "cus_4T8nQb2Wp1Zr",
                  "object": "customer",
                  "email": "anna@example.com",
                  "name": "Anna de Vries",
                  "phone": null,
                  "description": null,
                  "default_payment_method": null,
                  "metadata": {},
                  "livemode": false,
                  "created_at": "2026-07-16T09:20:04Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/customers/{id}": {
      "get": {
        "operationId": "retrieveCustomer",
        "tags": [
          "Customers"
        ],
        "summary": "Retrieve a customer",
        "description": "Returns the customer with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The customer id, prefixed `cus_`.",
            "schema": {
              "type": "string"
            },
            "example": "cus_4T8nQb2Wp1Zr"
          }
        ],
        "responses": {
          "200": {
            "description": "The customer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                },
                "example": {
                  "id": "cus_4T8nQb2Wp1Zr",
                  "object": "customer",
                  "email": "anna@example.com",
                  "name": "Anna de Vries",
                  "phone": null,
                  "description": null,
                  "default_payment_method": null,
                  "metadata": {},
                  "livemode": false,
                  "created_at": "2026-07-16T09:20:04Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "updateCustomer",
        "tags": [
          "Customers"
        ],
        "summary": "Update a customer",
        "description": "Updates the fields you pass; omitted fields are left unchanged. Set a field to `null` to clear it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The customer id, prefixed `cus_`.",
            "schema": {
              "type": "string"
            },
            "example": "cus_4T8nQb2Wp1Zr"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerRequest"
              },
              "example": {
                "default_payment_method": "pm_7Wq2xN9dT4Ls"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated customer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                },
                "example": {
                  "id": "cus_4T8nQb2Wp1Zr",
                  "object": "customer",
                  "email": "anna@example.com",
                  "name": "Anna de Vries",
                  "phone": null,
                  "description": null,
                  "default_payment_method": "pm_7Wq2xN9dT4Ls",
                  "metadata": {},
                  "livemode": false,
                  "created_at": "2026-07-16T09:20:04Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteCustomer",
        "tags": [
          "Customers"
        ],
        "summary": "Delete a customer",
        "description": "Permanently deletes a customer and detaches their saved payment methods. Historical payments are kept, with `customer` set to `null`. This cannot be undone.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The customer id, prefixed `cus_`.",
            "schema": {
              "type": "string"
            },
            "example": "cus_4T8nQb2Wp1Zr"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion confirmation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "id": "cus_4T8nQb2Wp1Zr",
                  "object": "customer",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payment_methods": {
      "get": {
        "operationId": "listPaymentMethods",
        "tags": [
          "Payment Methods"
        ],
        "summary": "List a customer's payment methods",
        "description": "Returns the payment methods attached to a customer. `customer` is required; filter further by `type`.",
        "parameters": [
          {
            "name": "customer",
            "in": "query",
            "required": true,
            "description": "The customer whose payment methods to list.",
            "schema": {
              "type": "string"
            },
            "example": "cus_4T8nQb2Wp1Zr"
          },
          {
            "name": "type",
            "in": "query",
            "description": "Only return payment methods of this type.",
            "schema": {
              "$ref": "#/components/schemas/PaymentMethodType"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of payment methods.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "pm_7Wq2xN9dT4Ls",
                      "object": "payment_method",
                      "type": "card",
                      "customer": "cus_4T8nQb2Wp1Zr",
                      "billing_details": {
                        "name": "Anna de Vries",
                        "email": "anna@example.com",
                        "phone": null,
                        "address": null
                      },
                      "card": {
                        "brand": "visa",
                        "last4": "4242",
                        "exp_month": 12,
                        "exp_year": 2028,
                        "funding": "debit",
                        "country": "NL"
                      },
                      "livemode": false,
                      "created_at": "2026-07-16T09:21:40Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/payment_methods"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createPaymentMethod",
        "tags": [
          "Payment Methods"
        ],
        "summary": "Create a payment method",
        "description": "Creates a reusable payment method, optionally attaching it to a customer at creation.\n\n**Card data:** raw card numbers are accepted **in test mode only** (use the [test cards](https://docs.finscale.dev/testing/)). In live mode, cards are tokenized by hosted checkout so card data never touches your servers — pass the resulting `token` here instead. Finscale is built to PCI DSS Level 1 standards.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentMethodRequest"
              },
              "example": {
                "type": "card",
                "customer": "cus_4T8nQb2Wp1Zr",
                "card": {
                  "number": "4242424242424242",
                  "exp_month": 12,
                  "exp_year": 2028,
                  "cvc": "123"
                },
                "billing_details": {
                  "name": "Anna de Vries",
                  "email": "anna@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The payment method.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethod"
                },
                "example": {
                  "id": "pm_7Wq2xN9dT4Ls",
                  "object": "payment_method",
                  "type": "card",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "billing_details": {
                    "name": "Anna de Vries",
                    "email": "anna@example.com",
                    "phone": null,
                    "address": null
                  },
                  "card": {
                    "brand": "visa",
                    "last4": "4242",
                    "exp_month": 12,
                    "exp_year": 2028,
                    "funding": "debit",
                    "country": "NL"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T09:21:40Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentDeclined"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payment_methods/{id}": {
      "get": {
        "operationId": "retrievePaymentMethod",
        "tags": [
          "Payment Methods"
        ],
        "summary": "Retrieve a payment method",
        "description": "Returns the payment method with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment method id, prefixed `pm_`.",
            "schema": {
              "type": "string"
            },
            "example": "pm_7Wq2xN9dT4Ls"
          }
        ],
        "responses": {
          "200": {
            "description": "The payment method.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethod"
                },
                "example": {
                  "id": "pm_7Wq2xN9dT4Ls",
                  "object": "payment_method",
                  "type": "card",
                  "customer": "cus_4T8nQb2Wp1Zr",
                  "billing_details": {
                    "name": "Anna de Vries",
                    "email": "anna@example.com",
                    "phone": null,
                    "address": null
                  },
                  "card": {
                    "brand": "visa",
                    "last4": "4242",
                    "exp_month": 12,
                    "exp_year": 2028,
                    "funding": "debit",
                    "country": "NL"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T09:21:40Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payment_methods/{id}/detach": {
      "post": {
        "operationId": "detachPaymentMethod",
        "tags": [
          "Payment Methods"
        ],
        "summary": "Detach a payment method",
        "description": "Detaches a payment method from its customer. Detached instruments can no longer be charged; past payments keep their `payment_method_details` snapshot.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payment method id, prefixed `pm_`.",
            "schema": {
              "type": "string"
            },
            "example": "pm_7Wq2xN9dT4Ls"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The detached payment method (`customer` is now `null`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethod"
                },
                "example": {
                  "id": "pm_7Wq2xN9dT4Ls",
                  "object": "payment_method",
                  "type": "card",
                  "customer": null,
                  "billing_details": {
                    "name": "Anna de Vries",
                    "email": "anna@example.com",
                    "phone": null,
                    "address": null
                  },
                  "card": {
                    "brand": "visa",
                    "last4": "4242",
                    "exp_month": 12,
                    "exp_year": 2028,
                    "funding": "debit",
                    "country": "NL"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T09:21:40Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/merchants": {
      "get": {
        "operationId": "listMerchants",
        "tags": [
          "Merchants"
        ],
        "summary": "List merchants",
        "description": "Returns your merchants, most recently created first. Filter by KYB status.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "kyb_status",
            "in": "query",
            "description": "Only return merchants with this KYB status.",
            "schema": {
              "type": "string",
              "enum": [
                "created",
                "kyb_pending",
                "under_review",
                "active",
                "restricted",
                "suspended"
              ]
            },
            "example": "active"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of merchants.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "mch_7Rq3wN8dK2Vs",
                      "object": "merchant",
                      "legal_name": "Aurora Retail B.V.",
                      "trading_name": "Aurora",
                      "country": "NL",
                      "mcc": "5734",
                      "mid": "845512000318",
                      "kyb_status": "active",
                      "capabilities": {
                        "card_payments": "active",
                        "local_methods": "active",
                        "payouts": "active"
                      },
                      "livemode": false,
                      "created_at": "2026-07-16T08:02:19Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/merchants"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createMerchant",
        "tags": [
          "Merchants"
        ],
        "summary": "Create a merchant",
        "description": "Creates a merchant and starts KYB onboarding — the merchant is returned in `kyb_status: kyb_pending` with all capabilities `pending` or `inactive` and no `mid` yet. Finscale collects the required verification data and documents through hosted onboarding; you track progress via `merchant.updated` events or by polling. Once checks pass, the merchant becomes `active`, capabilities activate, and a `mid` is assigned.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMerchantRequest"
              },
              "example": {
                "legal_name": "Aurora Retail B.V.",
                "trading_name": "Aurora",
                "country": "NL",
                "mcc": "5734"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The merchant, created in `kyb_status: kyb_pending`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Merchant"
                },
                "example": {
                  "id": "mch_7Rq3wN8dK2Vs",
                  "object": "merchant",
                  "legal_name": "Aurora Retail B.V.",
                  "trading_name": "Aurora",
                  "country": "NL",
                  "mcc": "5734",
                  "mid": null,
                  "kyb_status": "kyb_pending",
                  "capabilities": {
                    "card_payments": "pending",
                    "local_methods": "pending",
                    "payouts": "inactive"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T08:02:19Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/merchants/{id}": {
      "get": {
        "operationId": "retrieveMerchant",
        "tags": [
          "Merchants"
        ],
        "summary": "Retrieve a merchant",
        "description": "Returns the merchant with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The merchant id, prefixed `mch_`.",
            "schema": {
              "type": "string"
            },
            "example": "mch_7Rq3wN8dK2Vs"
          }
        ],
        "responses": {
          "200": {
            "description": "The merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Merchant"
                },
                "example": {
                  "id": "mch_7Rq3wN8dK2Vs",
                  "object": "merchant",
                  "legal_name": "Aurora Retail B.V.",
                  "trading_name": "Aurora",
                  "country": "NL",
                  "mcc": "5734",
                  "mid": "845512000318",
                  "kyb_status": "active",
                  "capabilities": {
                    "card_payments": "active",
                    "local_methods": "active",
                    "payouts": "active"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T08:02:19Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "updateMerchant",
        "tags": [
          "Merchants"
        ],
        "summary": "Update a merchant",
        "description": "Updates the fields you pass; omitted fields are left unchanged. `legal_name` and `country` are fixed at creation — a different legal entity means onboarding a new merchant. Changing `mcc` can send `kyb_status` back to `under_review` while the new line of business is checked.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The merchant id, prefixed `mch_`.",
            "schema": {
              "type": "string"
            },
            "example": "mch_7Rq3wN8dK2Vs"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMerchantRequest"
              },
              "example": {
                "trading_name": "Aurora Home"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Merchant"
                },
                "example": {
                  "id": "mch_7Rq3wN8dK2Vs",
                  "object": "merchant",
                  "legal_name": "Aurora Retail B.V.",
                  "trading_name": "Aurora Home",
                  "country": "NL",
                  "mcc": "5734",
                  "mid": "845512000318",
                  "kyb_status": "active",
                  "capabilities": {
                    "card_payments": "active",
                    "local_methods": "active",
                    "payouts": "active"
                  },
                  "livemode": false,
                  "created_at": "2026-07-16T08:02:19Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payouts": {
      "get": {
        "operationId": "listPayouts",
        "tags": [
          "Payouts"
        ],
        "summary": "List payouts",
        "description": "Returns payouts to your settlement bank account, most recent first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return payouts with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "in_transit",
                "paid",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of payouts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayoutList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "po_6Fn1mS8vQ2Xc",
                      "object": "payout",
                      "amount": 1914190,
                      "currency": "EUR",
                      "status": "paid",
                      "destination": {
                        "type": "iban",
                        "last4": "3401",
                        "country": "DE"
                      },
                      "arrival_date": "2026-07-18",
                      "settlement_report": "stl_2026_07_16_eu01",
                      "livemode": false,
                      "created_at": "2026-07-16T04:05:00Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/payouts"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payouts/{id}": {
      "get": {
        "operationId": "retrievePayout",
        "tags": [
          "Payouts"
        ],
        "summary": "Retrieve a payout",
        "description": "Returns the payout with the given id. `settlement_report` links to the report that reconciles it line by line.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The payout id, prefixed `po_`.",
            "schema": {
              "type": "string"
            },
            "example": "po_6Fn1mS8vQ2Xc"
          }
        ],
        "responses": {
          "200": {
            "description": "The payout.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payout"
                },
                "example": {
                  "id": "po_6Fn1mS8vQ2Xc",
                  "object": "payout",
                  "amount": 1914190,
                  "currency": "EUR",
                  "status": "paid",
                  "destination": {
                    "type": "iban",
                    "last4": "3401",
                    "country": "DE"
                  },
                  "arrival_date": "2026-07-18",
                  "settlement_report": "stl_2026_07_16_eu01",
                  "livemode": false,
                  "created_at": "2026-07-16T04:05:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/settlement_reports": {
      "get": {
        "operationId": "listSettlementReports",
        "tags": [
          "Settlement Reports"
        ],
        "summary": "List settlement reports",
        "description": "Returns settlement reports, newest period first. One report is generated per provider per settlement day; totals are already normalized to one shape, whatever the provider.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "provider",
            "in": "query",
            "description": "Only return reports for this provider id.",
            "schema": {
              "type": "string"
            },
            "example": "prov_eu_acq_01"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of settlement reports.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettlementReportList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "stl_2026_07_16_eu01",
                      "object": "settlement_report",
                      "period_start": "2026-07-15",
                      "period_end": "2026-07-16",
                      "provider": "prov_eu_acq_01",
                      "currency": "EUR",
                      "status": "ready",
                      "totals": {
                        "gross": 2041800,
                        "refunds": -96400,
                        "fees": -31210,
                        "net": 1914190
                      },
                      "transaction_count": 412,
                      "payout": "po_6Fn1mS8vQ2Xc",
                      "livemode": false,
                      "created_at": "2026-07-16T04:00:00Z"
                    }
                  ],
                  "has_more": true,
                  "url": "/v1/settlement_reports"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/settlement_reports/{id}": {
      "get": {
        "operationId": "retrieveSettlementReport",
        "tags": [
          "Settlement Reports"
        ],
        "summary": "Retrieve a settlement report",
        "description": "Returns a settlement report. Send `Accept: application/json` (default) for the summary object, or `Accept: text/csv` for the full transaction-level export — one row per payment, refund, and fee, with `payment_id` and merchant `reference` on every row so reconciliation is a join, not a hunt.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The settlement report id, prefixed `stl_`.",
            "schema": {
              "type": "string"
            },
            "example": "stl_2026_07_16_eu01"
          }
        ],
        "responses": {
          "200": {
            "description": "The settlement report — JSON summary or CSV export, by `Accept` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettlementReport"
                },
                "example": {
                  "id": "stl_2026_07_16_eu01",
                  "object": "settlement_report",
                  "period_start": "2026-07-15",
                  "period_end": "2026-07-16",
                  "provider": "prov_eu_acq_01",
                  "currency": "EUR",
                  "status": "ready",
                  "totals": {
                    "gross": 2041800,
                    "refunds": -96400,
                    "fees": -31210,
                    "net": 1914190
                  },
                  "transaction_count": 412,
                  "payout": "po_6Fn1mS8vQ2Xc",
                  "livemode": false,
                  "created_at": "2026-07-16T04:00:00Z"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Transaction-level CSV. Columns: `payment_id`, `reference`, `method`, `provider`, `gross`, `fee`, `net`, `currency`, `settled_at`. Amounts in minor units."
                },
                "example": "payment_id,reference,method,provider,gross,fee,net,currency,settled_at\npay_8Q2mX4nT1cVb,ord_9f21_0716,ideal,prov_eu_acq_02,4900,-64,4836,EUR,2026-07-16T04:00:00Z\npay_2Xw9cJ6pF3Md,ord_9f21_0716,card,prov_eu_acq_01,4900,-94,4806,EUR,2026-07-16T04:00:00Z\n"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "Events"
        ],
        "summary": "List events",
        "description": "Returns events from the last 30 days, most recent first. Use this to backfill after webhook downtime: list events since your last processed `created_at`, then resume.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "type",
            "in": "query",
            "description": "Only return events of this type.",
            "schema": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          {
            "name": "created_gte",
            "in": "query",
            "description": "Only return events created at or after this ISO 8601 timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "evt_5s8Y2kLmN0Ta",
                      "object": "event",
                      "type": "payment.succeeded",
                      "created_at": "2026-07-16T09:24:41Z",
                      "livemode": false,
                      "request_id": "req_7Hf3kQd2",
                      "data": {
                        "object": {
                          "id": "pay_8Q2mX4nT1cVb",
                          "object": "payment",
                          "amount": 4900,
                          "amount_captured": 4900,
                          "amount_refunded": 0,
                          "currency": "EUR",
                          "status": "succeeded",
                          "payment_method": "ideal",
                          "payment_method_id": null,
                          "payment_method_details": {
                            "ideal": {
                              "bank": "demo_bank_nl",
                              "iban_last4": "3401"
                            }
                          },
                          "capture_method": "automatic",
                          "customer": "cus_4T8nQb2Wp1Zr",
                          "description": null,
                          "reference": "ord_9f21_0716",
                          "metadata": {},
                          "provider": "prov_eu_acq_02",
                          "provider_attempts": [
                            {
                              "provider": "prov_eu_acq_01",
                              "outcome": "timeout",
                              "decline_code": null,
                              "latency_ms": 8003,
                              "attempted_at": "2026-07-16T09:24:31Z"
                            },
                            {
                              "provider": "prov_eu_acq_02",
                              "outcome": "approved",
                              "decline_code": null,
                              "latency_ms": 942,
                              "attempted_at": "2026-07-16T09:24:40Z"
                            }
                          ],
                          "risk": null,
                          "next_action": null,
                          "return_url": "https://shop.example.com/checkout/return",
                          "refunded": false,
                          "partially_refunded": false,
                          "failure_code": null,
                          "failure_message": null,
                          "livemode": false,
                          "created_at": "2026-07-16T09:24:31Z"
                        }
                      }
                    }
                  ],
                  "has_more": true,
                  "url": "/v1/events"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/events/{id}": {
      "get": {
        "operationId": "retrieveEvent",
        "tags": [
          "Events"
        ],
        "summary": "Retrieve an event",
        "description": "Returns the event with the given id. Handy as a webhook-handler pattern: receive the delivery, verify the signature, then fetch the event by id and act on the fetched copy.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The event id, prefixed `evt_`.",
            "schema": {
              "type": "string"
            },
            "example": "evt_5s8Y2kLmN0Ta"
          }
        ],
        "responses": {
          "200": {
            "description": "The event.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                },
                "example": {
                  "id": "evt_5s8Y2kLmN0Ta",
                  "object": "event",
                  "type": "payment.succeeded",
                  "created_at": "2026-07-16T09:24:41Z",
                  "livemode": false,
                  "request_id": "req_7Hf3kQd2",
                  "data": {
                    "object": {
                      "id": "pay_8Q2mX4nT1cVb",
                      "object": "payment",
                      "amount": 4900,
                      "amount_captured": 4900,
                      "amount_refunded": 0,
                      "currency": "EUR",
                      "status": "succeeded",
                      "payment_method": "ideal",
                      "payment_method_id": null,
                      "payment_method_details": {
                        "ideal": {
                          "bank": "demo_bank_nl",
                          "iban_last4": "3401"
                        }
                      },
                      "capture_method": "automatic",
                      "customer": "cus_4T8nQb2Wp1Zr",
                      "description": null,
                      "reference": "ord_9f21_0716",
                      "metadata": {},
                      "provider": "prov_eu_acq_02",
                      "provider_attempts": [
                        {
                          "provider": "prov_eu_acq_01",
                          "outcome": "timeout",
                          "decline_code": null,
                          "latency_ms": 8003,
                          "attempted_at": "2026-07-16T09:24:31Z"
                        },
                        {
                          "provider": "prov_eu_acq_02",
                          "outcome": "approved",
                          "decline_code": null,
                          "latency_ms": 942,
                          "attempted_at": "2026-07-16T09:24:40Z"
                        }
                      ],
                      "risk": null,
                      "next_action": null,
                      "return_url": "https://shop.example.com/checkout/return",
                      "refunded": false,
                      "partially_refunded": false,
                      "failure_code": null,
                      "failure_message": null,
                      "livemode": false,
                      "created_at": "2026-07-16T09:24:31Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhook_endpoints": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "List webhook endpoints",
        "description": "Returns your webhook endpoints. The signing `secret` is never included — it is only returned once, at creation.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of webhook endpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "wh_1KpZ7vRq",
                      "object": "webhook_endpoint",
                      "url": "https://example.com/webhooks/finscale",
                      "enabled_events": [
                        "payment.succeeded",
                        "payment.failed",
                        "refund.succeeded"
                      ],
                      "status": "enabled",
                      "api_version": "v1",
                      "livemode": false,
                      "created_at": "2026-07-10T11:00:00Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/webhook_endpoints"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Create a webhook endpoint",
        "description": "Registers an HTTPS URL to receive signed event deliveries. Subscribe to specific event types, or `[\"*\"]` for everything.\n\n**The response includes the signing `secret` (`whsec_…`) exactly once.** Store it now — it cannot be retrieved later, only rotated by creating a replacement endpoint. Verify every delivery against the `Finscale-Signature` header before trusting it; see [Webhooks](https://docs.finscale.dev/concepts/webhooks/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
              },
              "example": {
                "url": "https://example.com/webhooks/finscale",
                "enabled_events": [
                  "payment.succeeded",
                  "payment.failed",
                  "refund.succeeded"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook endpoint — the only response that ever contains `secret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecret"
                },
                "example": {
                  "id": "wh_1KpZ7vRq",
                  "object": "webhook_endpoint",
                  "url": "https://example.com/webhooks/finscale",
                  "enabled_events": [
                    "payment.succeeded",
                    "payment.failed",
                    "refund.succeeded"
                  ],
                  "status": "enabled",
                  "api_version": "v1",
                  "livemode": false,
                  "created_at": "2026-07-10T11:00:00Z",
                  "secret": "whsec_FinscaleDemo000…"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://api.finscale.dev/v1/webhook_endpoints \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\" \\\n  -H \"Idempotency-Key: idem_wh_setup_01\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"https://example.com/webhooks/finscale\",\n    \"enabled_events\": [\"payment.succeeded\", \"payment.failed\", \"refund.succeeded\"]\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch(\"https://api.finscale.dev/v1/webhook_endpoints\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n    \"Idempotency-Key\": \"idem_wh_setup_01\",\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({\n    url: \"https://example.com/webhooks/finscale\",\n    enabled_events: [\"payment.succeeded\", \"payment.failed\", \"refund.succeeded\"]\n  })\n});\nconst endpoint = await res.json();\n// endpoint.secret (whsec_…) is returned ONCE — store it now"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nres = requests.post(\n    \"https://api.finscale.dev/v1/webhook_endpoints\",\n    headers={\n        \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n        \"Idempotency-Key\": \"idem_wh_setup_01\",\n    },\n    json={\n        \"url\": \"https://example.com/webhooks/finscale\",\n        \"enabled_events\": [\"payment.succeeded\", \"payment.failed\", \"refund.succeeded\"],\n    },\n)\nendpoint = res.json()\n# endpoint[\"secret\"] (whsec_…) is returned ONCE — store it now"
          }
        ]
      }
    },
    "/webhook_endpoints/{id}": {
      "get": {
        "operationId": "retrieveWebhookEndpoint",
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Retrieve a webhook endpoint",
        "description": "Returns the webhook endpoint with the given id. Never includes the signing secret.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint id, prefixed `wh_`.",
            "schema": {
              "type": "string"
            },
            "example": "wh_1KpZ7vRq"
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "id": "wh_1KpZ7vRq",
                  "object": "webhook_endpoint",
                  "url": "https://example.com/webhooks/finscale",
                  "enabled_events": [
                    "payment.succeeded",
                    "payment.failed",
                    "refund.succeeded"
                  ],
                  "status": "enabled",
                  "api_version": "v1",
                  "livemode": false,
                  "created_at": "2026-07-10T11:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "updateWebhookEndpoint",
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Update a webhook endpoint",
        "description": "Updates the URL, subscribed events, or status. Set `status: disabled` to pause deliveries without losing the endpoint; missed events stay in `/v1/events` for 30 days.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint id, prefixed `wh_`.",
            "schema": {
              "type": "string"
            },
            "example": "wh_1KpZ7vRq"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
              },
              "example": {
                "enabled_events": [
                  "*"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "id": "wh_1KpZ7vRq",
                  "object": "webhook_endpoint",
                  "url": "https://example.com/webhooks/finscale",
                  "enabled_events": [
                    "*"
                  ],
                  "status": "enabled",
                  "api_version": "v1",
                  "livemode": false,
                  "created_at": "2026-07-10T11:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Delete a webhook endpoint",
        "description": "Permanently deletes a webhook endpoint. In-flight deliveries are abandoned. This cannot be undone.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint id, prefixed `wh_`.",
            "schema": {
              "type": "string"
            },
            "example": "wh_1KpZ7vRq"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion confirmation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "id": "wh_1KpZ7vRq",
                  "object": "webhook_endpoint",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/routing_rules": {
      "get": {
        "operationId": "listRoutingRules",
        "tags": [
          "Routing Rules"
        ],
        "summary": "List routing rules",
        "description": "Returns your routing rules ordered by `priority` ascending — the order they are evaluated in.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "name": "active",
            "in": "query",
            "description": "Only return rules with this active state.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of routing rules.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingRuleList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "rr_2Nc6wB4hJ9Ke",
                      "object": "routing_rule",
                      "priority": 10,
                      "active": true,
                      "description": "Prefer prov_eu_acq_02 for iDEAL in the Netherlands",
                      "match": {
                        "currency": "EUR",
                        "method": "ideal",
                        "country": "NL",
                        "amount_gte": null
                      },
                      "action": {
                        "type": "prefer_provider",
                        "provider": "prov_eu_acq_02"
                      },
                      "livemode": false,
                      "created_at": "2026-07-01T08:30:00Z"
                    },
                    {
                      "id": "rr_8Tf4qL1sV6Wd",
                      "object": "routing_rule",
                      "priority": 20,
                      "active": true,
                      "description": "Split EUR card volume 70/30 between EU acquirers",
                      "match": {
                        "currency": "EUR",
                        "method": "card",
                        "country": null,
                        "amount_gte": null
                      },
                      "action": {
                        "type": "weight_split",
                        "weights": [
                          {
                            "provider": "prov_eu_acq_01",
                            "weight": 70
                          },
                          {
                            "provider": "prov_eu_acq_02",
                            "weight": 30
                          }
                        ]
                      },
                      "livemode": false,
                      "created_at": "2026-07-01T08:31:00Z"
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/routing_rules"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createRoutingRule",
        "tags": [
          "Routing Rules"
        ],
        "summary": "Create a routing rule",
        "description": "Creates a routing rule. On every new payment, active rules are evaluated by ascending `priority`; the first rule whose `match` fits the transaction applies its `action`:\n\n- `prefer_provider` — try that provider first; smart routing still handles failover if it declines or times out.\n- `weight_split` — distribute matching volume across providers by weight (weights sum to 100). Useful for migrations and A/B-testing auth rates.\n- `block` — reject matching transactions before any provider is attempted (`failed`, code `blocked_by_routing_rule`).\n\nIf no rule matches, smart routing scores all eligible providers on cost, 7-day auth rate, currency, and method. See [Routing & providers](https://docs.finscale.dev/concepts/routing/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRoutingRuleRequest"
              },
              "example": {
                "priority": 10,
                "description": "Prefer prov_eu_acq_02 for iDEAL in the Netherlands",
                "match": {
                  "currency": "EUR",
                  "method": "ideal",
                  "country": "NL"
                },
                "action": {
                  "type": "prefer_provider",
                  "provider": "prov_eu_acq_02"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The routing rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingRule"
                },
                "example": {
                  "id": "rr_2Nc6wB4hJ9Ke",
                  "object": "routing_rule",
                  "priority": 10,
                  "active": true,
                  "description": "Prefer prov_eu_acq_02 for iDEAL in the Netherlands",
                  "match": {
                    "currency": "EUR",
                    "method": "ideal",
                    "country": "NL",
                    "amount_gte": null
                  },
                  "action": {
                    "type": "prefer_provider",
                    "provider": "prov_eu_acq_02"
                  },
                  "livemode": false,
                  "created_at": "2026-07-01T08:30:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "curl",
            "source": "curl https://api.finscale.dev/v1/routing_rules \\\n  -H \"Authorization: Bearer sk_test_51FinscaleDemo…\" \\\n  -H \"Idempotency-Key: idem_rr_ideal_nl\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"priority\": 10,\n    \"description\": \"Prefer prov_eu_acq_02 for iDEAL in the Netherlands\",\n    \"match\": { \"currency\": \"EUR\", \"method\": \"ideal\", \"country\": \"NL\" },\n    \"action\": { \"type\": \"prefer_provider\", \"provider\": \"prov_eu_acq_02\" }\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch(\"https://api.finscale.dev/v1/routing_rules\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n    \"Idempotency-Key\": \"idem_rr_ideal_nl\",\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({\n    priority: 10,\n    description: \"Prefer prov_eu_acq_02 for iDEAL in the Netherlands\",\n    match: { currency: \"EUR\", method: \"ideal\", country: \"NL\" },\n    action: { type: \"prefer_provider\", provider: \"prov_eu_acq_02\" }\n  })\n});\nconst rule = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nres = requests.post(\n    \"https://api.finscale.dev/v1/routing_rules\",\n    headers={\n        \"Authorization\": \"Bearer sk_test_51FinscaleDemo…\",\n        \"Idempotency-Key\": \"idem_rr_ideal_nl\",\n    },\n    json={\n        \"priority\": 10,\n        \"description\": \"Prefer prov_eu_acq_02 for iDEAL in the Netherlands\",\n        \"match\": {\"currency\": \"EUR\", \"method\": \"ideal\", \"country\": \"NL\"},\n        \"action\": {\"type\": \"prefer_provider\", \"provider\": \"prov_eu_acq_02\"},\n    },\n)\nrule = res.json()"
          }
        ]
      }
    },
    "/routing_rules/{id}": {
      "get": {
        "operationId": "retrieveRoutingRule",
        "tags": [
          "Routing Rules"
        ],
        "summary": "Retrieve a routing rule",
        "description": "Returns the routing rule with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The routing rule id, prefixed `rr_`.",
            "schema": {
              "type": "string"
            },
            "example": "rr_2Nc6wB4hJ9Ke"
          }
        ],
        "responses": {
          "200": {
            "description": "The routing rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingRule"
                },
                "example": {
                  "id": "rr_2Nc6wB4hJ9Ke",
                  "object": "routing_rule",
                  "priority": 10,
                  "active": true,
                  "description": "Prefer prov_eu_acq_02 for iDEAL in the Netherlands",
                  "match": {
                    "currency": "EUR",
                    "method": "ideal",
                    "country": "NL",
                    "amount_gte": null
                  },
                  "action": {
                    "type": "prefer_provider",
                    "provider": "prov_eu_acq_02"
                  },
                  "livemode": false,
                  "created_at": "2026-07-01T08:30:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "updateRoutingRule",
        "tags": [
          "Routing Rules"
        ],
        "summary": "Update a routing rule",
        "description": "Updates the fields you pass. Changes apply to new payments immediately; in-flight payments keep the rules they started with. Set `active: false` to switch a rule off without deleting it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The routing rule id, prefixed `rr_`.",
            "schema": {
              "type": "string"
            },
            "example": "rr_2Nc6wB4hJ9Ke"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRoutingRuleRequest"
              },
              "example": {
                "active": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated routing rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingRule"
                },
                "example": {
                  "id": "rr_2Nc6wB4hJ9Ke",
                  "object": "routing_rule",
                  "priority": 10,
                  "active": false,
                  "description": "Prefer prov_eu_acq_02 for iDEAL in the Netherlands",
                  "match": {
                    "currency": "EUR",
                    "method": "ideal",
                    "country": "NL",
                    "amount_gte": null
                  },
                  "action": {
                    "type": "prefer_provider",
                    "provider": "prov_eu_acq_02"
                  },
                  "livemode": false,
                  "created_at": "2026-07-01T08:30:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteRoutingRule",
        "tags": [
          "Routing Rules"
        ],
        "summary": "Delete a routing rule",
        "description": "Permanently deletes a routing rule. Matching traffic falls through to lower-priority rules, then to smart routing.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The routing rule id, prefixed `rr_`.",
            "schema": {
              "type": "string"
            },
            "example": "rr_2Nc6wB4hJ9Ke"
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion confirmation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "id": "rr_2Nc6wB4hJ9Ke",
                  "object": "routing_rule",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/providers": {
      "get": {
        "operationId": "listProviders",
        "tags": [
          "Providers"
        ],
        "summary": "List providers",
        "description": "Returns the providers available to your account. Read-only — providers are managed by Finscale and exposed as opaque `prov_*` ids. Watch `status` and `auth_rate_7d` here, or subscribe to `provider.health.changed` webhooks; smart routing already down-weights `degraded` providers automatically.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of providers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "prov_eu_acq_01",
                      "object": "provider",
                      "methods": [
                        "card",
                        "ideal",
                        "bancontact",
                        "eps",
                        "sepa_debit",
                        "sepa_credit",
                        "apple_pay",
                        "google_pay"
                      ],
                      "regions": [
                        "EU",
                        "UK"
                      ],
                      "currencies": [
                        "EUR",
                        "GBP",
                        "PLN",
                        "SEK",
                        "DKK",
                        "CHF"
                      ],
                      "status": "active",
                      "auth_rate_7d": 0.947
                    },
                    {
                      "id": "prov_eu_acq_02",
                      "object": "provider",
                      "methods": [
                        "card",
                        "ideal",
                        "blik",
                        "p24",
                        "trustly",
                        "mobilepay",
                        "vipps",
                        "swish",
                        "twint",
                        "apple_pay",
                        "google_pay"
                      ],
                      "regions": [
                        "EU"
                      ],
                      "currencies": [
                        "EUR",
                        "PLN",
                        "NOK",
                        "SEK",
                        "DKK",
                        "CHF"
                      ],
                      "status": "active",
                      "auth_rate_7d": 0.951
                    },
                    {
                      "id": "prov_us_psp_01",
                      "object": "provider",
                      "methods": [
                        "card",
                        "ach",
                        "apple_pay",
                        "google_pay",
                        "usdc"
                      ],
                      "regions": [
                        "US",
                        "CA"
                      ],
                      "currencies": [
                        "USD",
                        "CAD"
                      ],
                      "status": "degraded",
                      "auth_rate_7d": 0.902
                    },
                    {
                      "id": "prov_br_psp_01",
                      "object": "provider",
                      "methods": [
                        "card",
                        "pix"
                      ],
                      "regions": [
                        "BR"
                      ],
                      "currencies": [
                        "BRL"
                      ],
                      "status": "active",
                      "auth_rate_7d": 0.938
                    }
                  ],
                  "has_more": false,
                  "url": "/v1/providers"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/providers/{id}": {
      "get": {
        "operationId": "retrieveProvider",
        "tags": [
          "Providers"
        ],
        "summary": "Retrieve a provider",
        "description": "Returns the provider with the given id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The provider id, prefixed `prov_`.",
            "schema": {
              "type": "string"
            },
            "example": "prov_eu_acq_01"
          }
        ],
        "responses": {
          "200": {
            "description": "The provider.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Provider"
                },
                "example": {
                  "id": "prov_eu_acq_01",
                  "object": "provider",
                  "methods": [
                    "card",
                    "ideal",
                    "bancontact",
                    "eps",
                    "sepa_debit",
                    "sepa_credit",
                    "apple_pay",
                    "google_pay"
                  ],
                  "regions": [
                    "EU",
                    "UK"
                  ],
                  "currencies": [
                    "EUR",
                    "GBP",
                    "PLN",
                    "SEK",
                    "DKK",
                    "CHF"
                  ],
                  "status": "active",
                  "auth_rate_7d": 0.947
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/balance": {
      "get": {
        "operationId": "retrieveBalance",
        "tags": [
          "Balance"
        ],
        "summary": "Retrieve balance",
        "description": "Returns your current balance per currency. `available` is settled and payable; `pending` is captured but not yet settled by the providers. The split already accounts for per-provider settlement timing — you see one number, not four provider statements.",
        "responses": {
          "200": {
            "description": "The balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "object": "balance",
                  "available": [
                    {
                      "amount": 1914190,
                      "currency": "EUR"
                    },
                    {
                      "amount": 402100,
                      "currency": "USD"
                    }
                  ],
                  "pending": [
                    {
                      "amount": 68400,
                      "currency": "EUR"
                    }
                  ],
                  "livemode": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "webhooks": {
    "payment.succeeded": {
      "post": {
        "operationId": "webhookPaymentSucceeded",
        "summary": "payment.succeeded",
        "description": "Sent when a payment reaches `succeeded`. Verify `Finscale-Signature` before trusting the payload: recompute HMAC-SHA256 of `\"<t>.<raw body>\"` with your `whsec_…` secret and compare to `v1`. Reject if the timestamp is older than 5 minutes.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_5s8Y2kLmN0Ta",
                "object": "event",
                "type": "payment.succeeded",
                "created_at": "2026-07-16T09:24:41Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "pay_8Q2mX4nT1cVb",
                    "object": "payment",
                    "amount": 4900,
                    "amount_captured": 4900,
                    "amount_refunded": 0,
                    "currency": "EUR",
                    "status": "succeeded",
                    "payment_method": "ideal",
                    "payment_method_id": null,
                    "payment_method_details": {
                      "ideal": {
                        "bank": "demo_bank_nl",
                        "iban_last4": "3401"
                      }
                    },
                    "capture_method": "automatic",
                    "customer": "cus_4T8nQb2Wp1Zr",
                    "description": null,
                    "reference": "ord_9f21_0716",
                    "metadata": {},
                    "provider": "prov_eu_acq_02",
                    "provider_attempts": [
                      {
                        "provider": "prov_eu_acq_01",
                        "outcome": "timeout",
                        "decline_code": null,
                        "latency_ms": 8003,
                        "attempted_at": "2026-07-16T09:24:31Z"
                      },
                      {
                        "provider": "prov_eu_acq_02",
                        "outcome": "approved",
                        "decline_code": null,
                        "latency_ms": 942,
                        "attempted_at": "2026-07-16T09:24:40Z"
                      }
                    ],
                    "risk": null,
                    "next_action": null,
                    "return_url": "https://shop.example.com/checkout/return",
                    "refunded": false,
                    "partially_refunded": false,
                    "failure_code": null,
                    "failure_message": null,
                    "livemode": false,
                    "created_at": "2026-07-16T09:24:31Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly (within 10 s). Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "payment.failed": {
      "post": {
        "operationId": "webhookPaymentFailed",
        "summary": "payment.failed",
        "description": "Sent when a payment reaches `failed` — after all eligible providers were attempted. `data.object.provider_attempts` shows every attempt and decline code.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_9r2W7xPqM4Vb",
                "object": "event",
                "type": "payment.failed",
                "created_at": "2026-07-16T09:24:41Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "pay_8Q2mX4nT1cVb",
                    "object": "payment",
                    "amount": 4900,
                    "amount_captured": 0,
                    "amount_refunded": 0,
                    "currency": "EUR",
                    "status": "failed",
                    "payment_method": "ideal",
                    "payment_method_id": null,
                    "payment_method_details": null,
                    "capture_method": "automatic",
                    "customer": "cus_4T8nQb2Wp1Zr",
                    "description": null,
                    "reference": "ord_9f21_0716",
                    "metadata": {},
                    "provider": null,
                    "provider_attempts": [
                      {
                        "provider": "prov_eu_acq_01",
                        "outcome": "declined",
                        "decline_code": "insufficient_funds",
                        "latency_ms": 720,
                        "attempted_at": "2026-07-16T09:24:31Z"
                      },
                      {
                        "provider": "prov_eu_acq_02",
                        "outcome": "declined",
                        "decline_code": "insufficient_funds",
                        "latency_ms": 655,
                        "attempted_at": "2026-07-16T09:24:33Z"
                      }
                    ],
                    "risk": null,
                    "next_action": null,
                    "return_url": "https://shop.example.com/checkout/return",
                    "refunded": false,
                    "partially_refunded": false,
                    "failure_code": "insufficient_funds",
                    "failure_message": "The customer's account has insufficient funds.",
                    "livemode": false,
                    "created_at": "2026-07-16T09:24:31Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "payment.risk_review": {
      "post": {
        "operationId": "webhookPaymentRiskReview",
        "summary": "payment.risk_review",
        "description": "Sent when risk screening holds a payment for manual review (`risk.decision: \"review\"`). The payment stays in `processing` while the review is open: approve it in the dashboard and it routes normally (`payment.succeeded` / `payment.failed` follows); block it and it fails with `failure_code: payment_blocked`. Verify `Finscale-Signature` before trusting the payload.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_4k9D2mWpR7Xc",
                "object": "event",
                "type": "payment.risk_review",
                "created_at": "2026-07-16T11:08:45Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "pay_6Rd8wQ3nX5Kt",
                    "object": "payment",
                    "amount": 18900,
                    "amount_captured": 0,
                    "amount_refunded": 0,
                    "currency": "EUR",
                    "status": "processing",
                    "payment_method": "card",
                    "payment_method_id": "pm_7Wq2xN9dT4Ls",
                    "payment_method_details": {
                      "card": {
                        "brand": "visa",
                        "last4": "4242",
                        "exp_month": 12,
                        "exp_year": 2028,
                        "funding": "debit",
                        "country": "NL"
                      }
                    },
                    "capture_method": "automatic",
                    "customer": "cus_4T8nQb2Wp1Zr",
                    "description": null,
                    "reference": "ord_9f21_0716",
                    "metadata": {},
                    "provider": null,
                    "provider_attempts": [],
                    "risk": {
                      "score": 82,
                      "decision": "review",
                      "checks": {
                        "avs_result": "pass",
                        "cvv_result": "pass"
                      }
                    },
                    "next_action": null,
                    "return_url": null,
                    "refunded": false,
                    "partially_refunded": false,
                    "failure_code": null,
                    "failure_message": null,
                    "livemode": false,
                    "created_at": "2026-07-16T11:08:44Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "refund.succeeded": {
      "post": {
        "operationId": "webhookRefundSucceeded",
        "summary": "refund.succeeded",
        "description": "Sent when a refund settles successfully at the original provider.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_2b6C9dRtE1Wq",
                "object": "event",
                "type": "refund.succeeded",
                "created_at": "2026-07-16T14:03:20Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "rf_3Vp7dK2wQx",
                    "object": "refund",
                    "amount": 4900,
                    "currency": "EUR",
                    "payment": "pay_8Q2mX4nT1cVb",
                    "reason": "requested_by_customer",
                    "status": "succeeded",
                    "provider": "prov_eu_acq_02",
                    "failure_code": null,
                    "metadata": {},
                    "livemode": false,
                    "created_at": "2026-07-16T14:02:11Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "dispute.created": {
      "post": {
        "operationId": "webhookDisputeCreated",
        "summary": "dispute.created",
        "description": "Sent when a dispute (chargeback) is opened against a payment. The disputed amount is withheld from your balance while the dispute runs. Check `evidence_due_by` and respond in time — submit evidence or accept. Later stage/status changes arrive as `dispute.updated`; the final outcome arrives as `dispute.closed`. Verify `Finscale-Signature` before trusting the payload.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_8Wn3xK7qP2Rd",
                "object": "event",
                "type": "dispute.created",
                "created_at": "2026-07-16T18:40:23Z",
                "livemode": false,
                "request_id": null,
                "data": {
                  "object": {
                    "id": "dp_5Kw2mR8vQz1N",
                    "object": "dispute",
                    "payment": "pay_3Vt7Kd9sLm2x",
                    "amount": 12900,
                    "currency": "EUR",
                    "reason": "fraudulent",
                    "stage": "chargeback",
                    "status": "needs_response",
                    "evidence_due_by": "2026-07-30T23:59:59Z",
                    "livemode": false,
                    "created_at": "2026-07-16T18:40:22Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "settlement.report.ready": {
      "post": {
        "operationId": "webhookSettlementReportReady",
        "summary": "settlement.report.ready",
        "description": "Sent when a settlement report finishes generating. Fetch the CSV with `GET /settlement_reports/{id}` and `Accept: text/csv`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_7k1M3nQwB8Xd",
                "object": "event",
                "type": "settlement.report.ready",
                "created_at": "2026-07-16T04:00:02Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "stl_2026_07_16_eu01",
                    "object": "settlement_report",
                    "period_start": "2026-07-15",
                    "period_end": "2026-07-16",
                    "provider": "prov_eu_acq_01",
                    "currency": "EUR",
                    "status": "ready",
                    "totals": {
                      "gross": 2041800,
                      "refunds": -96400,
                      "fees": -31210,
                      "net": 1914190
                    },
                    "transaction_count": 412,
                    "payout": "po_6Fn1mS8vQ2Xc",
                    "livemode": false,
                    "created_at": "2026-07-16T04:00:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    },
    "provider.health.changed": {
      "post": {
        "operationId": "webhookProviderHealthChanged",
        "summary": "provider.health.changed",
        "description": "Sent when a provider's `status` changes (e.g. `active` → `degraded`). Informational — smart routing already reacts; no merchant action is required.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FinscaleSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_4h8J2mVsC6Yf",
                "object": "event",
                "type": "provider.health.changed",
                "created_at": "2026-07-16T07:12:44Z",
                "livemode": false,
                "request_id": "req_7Hf3kQd2",
                "data": {
                  "object": {
                    "id": "prov_us_psp_01",
                    "object": "provider",
                    "methods": [
                      "card",
                      "ach",
                      "apple_pay",
                      "google_pay",
                      "usdc"
                    ],
                    "regions": [
                      "US",
                      "CA"
                    ],
                    "currencies": [
                      "USD",
                      "CAD"
                    ],
                    "status": "degraded",
                    "auth_rate_7d": 0.902
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx quickly. Non-2xx responses are retried with exponential backoff for 72 hours."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "secret_key": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your secret API key as a Bearer token: `Authorization: Bearer sk_test_51FinscaleDemo…`. Test keys are prefixed `sk_test_`, live keys `sk_live_` (always store server-side; shown redacted as `sk_live_••••••••••••`). Keys are account-scoped and rotatable from the dashboard."
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Number of objects to return, 1–100. Default 20.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        },
        "example": 20
      },
      "StartingAfter": {
        "name": "starting_after",
        "in": "query",
        "description": "Cursor for forward pagination: the id of the last object on the previous page. Returns objects created after it in list order.",
        "schema": {
          "type": "string"
        },
        "example": "pay_8Q2mX4nT1cVb"
      },
      "EndingBefore": {
        "name": "ending_before",
        "in": "query",
        "description": "Cursor for backward pagination: the id of the first object on the current page. Mutually exclusive with `starting_after`.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "description": "Unique key (≤ 255 chars) that makes this POST safe to retry. Replays within 24 hours return the original response with the same status code; the same key with a different payload returns `409 idempotency_error`. Strongly recommended on every POST.",
        "schema": {
          "type": "string",
          "maxLength": 255
        },
        "example": "idem_ord_9f21_0716"
      },
      "FinscaleSignature": {
        "name": "Finscale-Signature",
        "in": "header",
        "required": true,
        "description": "Webhook signature: `t=<unix timestamp>,v1=<hex HMAC-SHA256 of \"t.body\" keyed with your whsec_… secret>`. Verify before processing; reject stale timestamps (> 5 minutes).",
        "schema": {
          "type": "string"
        },
        "example": "t=1752657881,v1=5f8c3a0e97b1d64a2c9f0b7e8d3a1c5f9e2b4d6a8c0e1f3a5b7d9c2e4f6a8b0d"
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request — a parameter is missing, malformed, or the object is in the wrong state for this call.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "parameter_invalid",
                "message": "amount must be a positive integer in minor units.",
                "param": "amount",
                "doc_url": "https://docs.finscale.dev/errors/",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "api_key_invalid",
                "message": "No valid API key provided. Pass your secret key as a Bearer token in the Authorization header.",
                "doc_url": "https://docs.finscale.dev/authentication/",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      },
      "PaymentDeclined": {
        "description": "The payment could not be completed — e.g. the card was declined by every eligible provider.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "card_error",
                "code": "card_declined",
                "message": "The card was declined by the issuer.",
                "doc_url": "https://docs.finscale.dev/errors/#card_declined",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "No object with that id exists in this mode (test vs live).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "resource_missing",
                "message": "No such payment: pay_0000000000. Check the id and the mode of the key you are using (test vs live).",
                "doc_url": "https://docs.finscale.dev/errors/",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "The `Idempotency-Key` was already used with a different request payload.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "idempotency_error",
                "code": "idempotency_key_reused",
                "message": "The Idempotency-Key 'idem_ord_9f21_0716' was reused with a different request payload.",
                "doc_url": "https://docs.finscale.dev/idempotency/",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests. Honor the `Retry-After` header and back off exponentially.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            },
            "example": 2
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
                "message": "Too many requests. Retry after the number of seconds given in the Retry-After header.",
                "doc_url": "https://docs.finscale.dev/errors/#rate_limit_error",
                "request_id": "req_7Hf3kQd2"
              }
            }
          }
        }
      }
    },
    "schemas": {
      "PaymentStatus": {
        "type": "string",
        "enum": [
          "requires_confirmation",
          "requires_action",
          "requires_capture",
          "processing",
          "succeeded",
          "failed",
          "canceled"
        ],
        "description": "The payment lifecycle:\n\n- `requires_confirmation` — created with `confirm: false`, waiting for your confirm call.\n- `requires_action` — waiting on the customer (e.g. a redirect to their bank).\n- `requires_capture` — card authorized (`capture_method: manual`), waiting for capture.\n- `processing` — submitted to a provider, outcome pending; also where a payment holds while risk review is open (`risk.decision: \"review\"`).\n- `succeeded` — funds captured. Terminal.\n- `failed` — all eligible providers declined or errored. Terminal.\n- `canceled` — canceled before completion. Terminal.",
        "examples": [
          "succeeded"
        ]
      },
      "PaymentMethodType": {
        "type": "string",
        "enum": [
          "card",
          "apple_pay",
          "google_pay",
          "paypal",
          "usdc",
          "upi",
          "ideal",
          "bancontact",
          "blik",
          "p24",
          "pix",
          "boleto",
          "mb_way",
          "multibanco",
          "trustly",
          "eps",
          "satispay",
          "mobilepay",
          "vipps",
          "swish",
          "twint",
          "klarna",
          "affirm",
          "afterpay_clearpay",
          "cashapp",
          "alipay",
          "wechat_pay",
          "kakao_pay",
          "konbini",
          "grabpay",
          "gopay",
          "fpx",
          "paynow",
          "promptpay",
          "mpesa",
          "oxxo",
          "spei",
          "sepa_debit",
          "sepa_credit",
          "ach",
          "bacs_debit",
          "becs_debit",
          "acss_debit"
        ],
        "description": "Payment method types — the full 40+ method catalog. `card` covers all major schemes; wallets (`apple_pay`, `google_pay`, `paypal`, `alipay`, `wechat_pay`, `cashapp`, `kakao_pay`, …), bank redirects (`ideal`, `bancontact`, `eps`, `p24`, `fpx`, `trustly`), real-time rails (`upi`, `pix`, `blik`, `swish`, `paynow`, `promptpay`, `mb_way`), buy now pay later (`klarna`, `affirm`, `afterpay_clearpay`), vouchers (`oxxo`, `boleto`, `konbini`, `multibanco`), direct debit under mandate (`sepa_debit`, `ach`, `bacs_debit`, `becs_debit`, `acss_debit`), bank transfers (`sepa_credit`, `spei`), mobile money (`mpesa`), and `usdc` settling as stablecoin. See [Payment methods](https://docs.finscale.dev/concepts/payment-methods/).",
        "examples": [
          "ideal"
        ]
      },
      "EventType": {
        "type": "string",
        "enum": [
          "payment.processing",
          "payment.succeeded",
          "payment.failed",
          "payment.requires_action",
          "payment.risk_review",
          "refund.succeeded",
          "refund.failed",
          "dispute.created",
          "dispute.updated",
          "dispute.closed",
          "merchant.updated",
          "settlement.report.ready",
          "provider.health.changed"
        ],
        "description": "Every event type Finscale emits.",
        "examples": [
          "payment.succeeded"
        ]
      },
      "ProviderAttempt": {
        "type": "object",
        "description": "One routing attempt at one provider. The array of attempts on a payment is the full audit trail of smart routing and failover.",
        "required": [
          "provider",
          "outcome",
          "attempted_at"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "description": "Opaque provider id the attempt was routed to.",
            "examples": [
              "prov_eu_acq_01"
            ]
          },
          "outcome": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "declined",
              "timeout",
              "error"
            ],
            "description": "Result of this attempt. `timeout` and `error` trigger automatic failover to the next eligible provider; `declined` fails over when the decline code is retryable."
          },
          "decline_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized decline code when `outcome` is `declined` (e.g. `insufficient_funds`, `do_not_honor`). Otherwise `null`.",
            "examples": [
              "insufficient_funds"
            ]
          },
          "latency_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Round-trip latency to the provider in milliseconds. `null` while the attempt is `pending`.",
            "examples": [
              942
            ]
          },
          "attempted_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the attempt was started, ISO 8601 UTC."
          }
        }
      },
      "NextAction": {
        "type": [
          "object",
          "null"
        ],
        "description": "What must happen next to advance the payment, or `null` when nothing is required from you.",
        "required": [
          "type",
          "url"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "redirect"
            ],
            "description": "Action kind. `redirect`: send the customer to `url`; they return to your `return_url` when done."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Finscale-hosted URL that takes the customer through the method's flow (bank selection, app approval, 3-D Secure…).",
            "examples": [
              "https://pay.finscale.dev/r/8Q2mX4nT"
            ]
          }
        }
      },
      "PaymentMethodDetails": {
        "type": [
          "object",
          "null"
        ],
        "description": "Snapshot of the instrument that (last) processed this payment, keyed by method type — e.g. `card: { brand, last4, exp_month, exp_year, funding, country }` or `ideal: { bank, iban_last4 }`. Populated once a provider attempt completes; `null` before that.",
        "properties": {
          "card": {
            "type": "object",
            "description": "Present when the payment method is `card`.",
            "properties": {
              "brand": {
                "type": "string",
                "description": "Card brand, e.g. `visa`, `mastercard`.",
                "examples": [
                  "visa"
                ]
              },
              "last4": {
                "type": "string",
                "description": "Last four digits.",
                "examples": [
                  "4242"
                ]
              },
              "exp_month": {
                "type": "integer",
                "minimum": 1,
                "maximum": 12,
                "description": "Expiry month (1–12)."
              },
              "exp_year": {
                "type": "integer",
                "description": "Four-digit expiry year.",
                "examples": [
                  2028
                ]
              },
              "funding": {
                "type": "string",
                "enum": [
                  "credit",
                  "debit",
                  "prepaid",
                  "unknown"
                ],
                "description": "Funding type."
              },
              "country": {
                "type": "string",
                "description": "Two-letter issuing country.",
                "examples": [
                  "NL"
                ]
              }
            }
          },
          "ideal": {
            "type": "object",
            "description": "Present when the payment method is `ideal`.",
            "properties": {
              "bank": {
                "type": "string",
                "description": "Customer's bank identifier.",
                "examples": [
                  "demo_bank_nl"
                ]
              },
              "iban_last4": {
                "type": "string",
                "description": "Last four characters of the paying IBAN.",
                "examples": [
                  "3401"
                ]
              }
            }
          },
          "sepa_debit": {
            "type": "object",
            "description": "Present when the payment method is `sepa_debit`.",
            "properties": {
              "iban_last4": {
                "type": "string",
                "description": "Last four characters of the debited IBAN."
              },
              "mandate_reference": {
                "type": "string",
                "description": "SEPA mandate reference."
              }
            }
          }
        },
        "additionalProperties": true
      },
      "PaymentRisk": {
        "type": [
          "object",
          "null"
        ],
        "description": "Risk assessment for the payment. Populated once risk screening runs — always for card-family payments (`card`, `apple_pay`, `google_pay`); `null` for methods that are not risk-scored, such as bank redirects where the customer authenticates at their bank.\n\nWhen `decision` is `review`, the payment holds in `processing` and a `payment.risk_review` event fires — approve or block it in the dashboard. When `decision` is `blocked`, the payment moves to `failed` with `failure_code: payment_blocked` and no provider is attempted.",
        "required": [
          "score",
          "decision"
        ],
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 99,
            "description": "Composite risk score, `0` (lowest risk) to `99` (highest). Deterministic in test mode.",
            "examples": [
              17
            ]
          },
          "decision": {
            "type": "string",
            "enum": [
              "approved",
              "review",
              "blocked"
            ],
            "description": "What risk screening decided: `approved` — proceed to routing; `review` — held in `processing` for manual review; `blocked` — refused, the payment `failed` with `failure_code: payment_blocked`."
          },
          "checks": {
            "type": "object",
            "description": "Instrument verification results that fed the score.",
            "properties": {
              "avs_result": {
                "type": "string",
                "enum": [
                  "pass",
                  "fail",
                  "unavailable"
                ],
                "description": "Address Verification System result: the billing address matched (`pass`), did not match (`fail`), or the issuer/method does not support AVS (`unavailable`)."
              },
              "cvv_result": {
                "type": "string",
                "enum": [
                  "pass",
                  "fail",
                  "unavailable"
                ],
                "description": "Card verification code result: matched (`pass`), did not match (`fail`), or not checked (`unavailable`)."
              }
            }
          }
        }
      },
      "Payment": {
        "type": "object",
        "description": "A Payment is one attempt to collect money from a customer. Finscale routes it across providers; `provider_attempts` records every hop, `provider` is the one that (last) processed it.",
        "required": [
          "id",
          "object",
          "amount",
          "currency",
          "status",
          "payment_method",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the payment. Always prefixed `pay_`.",
            "examples": [
              "pay_8Q2mX4nT1cVb"
            ]
          },
          "object": {
            "type": "string",
            "const": "payment",
            "description": "String representing the object's type. Always `payment`."
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Amount in the smallest currency unit (minor units). €49.00 is `4900`. Zero-decimal handling follows ISO 4217 exponents.",
            "examples": [
              4900
            ]
          },
          "amount_captured": {
            "type": "integer",
            "description": "Amount captured so far, in minor units. Equals `amount` after a full capture or an automatic-capture success.",
            "examples": [
              4900
            ]
          },
          "amount_refunded": {
            "type": "integer",
            "description": "Total refunded so far, in minor units.",
            "examples": [
              0
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/PaymentStatus"
          },
          "payment_method": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentMethodType"
              }
            ],
            "description": "The payment method type used for this payment."
          },
          "payment_method_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the saved payment method (`pm_…`) used, if one was; `null` for one-off method types like a fresh iDEAL redirect.",
            "examples": [
              "pm_7Wq2xN9dT4Ls"
            ]
          },
          "payment_method_details": {
            "$ref": "#/components/schemas/PaymentMethodDetails"
          },
          "capture_method": {
            "type": "string",
            "enum": [
              "automatic",
              "manual"
            ],
            "default": "automatic",
            "description": "`automatic` captures on approval. `manual` (cards only) authorizes first; capture within 7 days via the capture endpoint."
          },
          "customer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the customer this payment belongs to, or `null`.",
            "examples": [
              "cus_4T8nQb2Wp1Zr"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text description, shown in the dashboard and reports."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your reference for this payment — typically your order id. Echoed in webhooks, settlement CSVs, and list filters. Not required to be unique.",
            "examples": [
              "ord_9f21_0716"
            ]
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          },
          "provider": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque id of the provider that is processing (or last processed) this payment. `null` before routing and after cancellation.",
            "examples": [
              "prov_eu_acq_01"
            ]
          },
          "provider_attempts": {
            "type": "array",
            "description": "Every provider attempt for this payment, in order. One entry for the happy path; more when failover kicked in.",
            "items": {
              "$ref": "#/components/schemas/ProviderAttempt"
            }
          },
          "risk": {
            "$ref": "#/components/schemas/PaymentRisk"
          },
          "next_action": {
            "$ref": "#/components/schemas/NextAction"
          },
          "return_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Where the customer is sent back to after completing a redirect action. Required for redirect methods.",
            "examples": [
              "https://shop.example.com/checkout/return"
            ]
          },
          "refunded": {
            "type": "boolean",
            "description": "`true` once the payment is fully refunded (`amount_refunded` = `amount_captured`)."
          },
          "partially_refunded": {
            "type": "boolean",
            "description": "`true` while the payment is partially refunded (`0` < `amount_refunded` < `amount_captured`). Mutually exclusive with `refunded`."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized failure code when `status` is `failed` (e.g. `insufficient_funds`); otherwise `null`."
          },
          "failure_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable explanation of the failure, safe to log — never show it verbatim to customers."
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "CreatePaymentRequest": {
        "type": "object",
        "description": "Payload for creating a payment.",
        "required": [
          "amount",
          "currency",
          "payment_method"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Amount to collect, in minor units. €49.00 is `4900`. In test mode, `4999` forces a first-provider timeout to demonstrate failover, `4002` fails with a final `card_declined` decline, `4991` forces a risk `review` hold, and `4992` is blocked by risk screening.",
            "examples": [
              4900
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "payment_method": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentMethodType"
              }
            ],
            "description": "The payment method type to collect with."
          },
          "payment_method_id": {
            "type": "string",
            "description": "Charge a saved instrument instead: the `pm_…` id of a payment method attached to `customer`."
          },
          "reference": {
            "type": "string",
            "maxLength": 128,
            "description": "Your reference for this payment — typically your order id.",
            "examples": [
              "ord_9f21_0716"
            ]
          },
          "customer": {
            "type": "object",
            "description": "Attach the payment to a customer: pass `{ \"id\": \"cus_…\" }` for an existing one, or an inline `email`/`name` to create (or reuse, matched on email) a customer on the fly.",
            "properties": {
              "id": {
                "type": "string",
                "description": "Existing customer id.",
                "examples": [
                  "cus_4T8nQb2Wp1Zr"
                ]
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "Customer email.",
                "examples": [
                  "anna@example.com"
                ]
              },
              "name": {
                "type": "string",
                "description": "Customer name.",
                "examples": [
                  "Anna de Vries"
                ]
              }
            }
          },
          "description": {
            "type": "string",
            "description": "Free-text description for the dashboard and reports."
          },
          "capture_method": {
            "type": "string",
            "enum": [
              "automatic",
              "manual"
            ],
            "default": "automatic",
            "description": "`manual` (cards only) authorizes now and captures later."
          },
          "confirm": {
            "type": "boolean",
            "default": true,
            "description": "`false` creates the payment in `requires_confirmation` without routing it; confirm later with the confirm endpoint."
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "description": "Where to send the customer after a redirect flow completes. Required for redirect methods (iDEAL, Bancontact, Blik, PIX, …).",
            "examples": [
              "https://shop.example.com/checkout/return"
            ]
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          }
        }
      },
      "ConfirmPaymentRequest": {
        "type": "object",
        "description": "Optional payload for confirming a payment.",
        "properties": {
          "payment_method_id": {
            "type": "string",
            "description": "Switch the instrument at confirm time: a `pm_…` id attached to the payment's customer.",
            "examples": [
              "pm_7Wq2xN9dT4Ls"
            ]
          }
        }
      },
      "CapturePaymentRequest": {
        "type": "object",
        "description": "Optional payload for capturing an authorized payment.",
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Amount to capture, in minor units. Must be ≤ the remaining authorized amount. Omit to capture the remainder in full. A smaller `amount` performs a partial capture; where the network supports multiple capture the payment stays `requires_capture` so you can capture again — otherwise the remainder is released.",
            "examples": [
              4900
            ]
          }
        }
      },
      "IncrementAuthorizationRequest": {
        "type": "object",
        "description": "Payload for incrementing an authorization.",
        "required": [
          "amount"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "The **new total** authorization amount in minor units — not the delta. Must be greater than the current `amount`; the issuer approves the difference.",
            "examples": [
              6900
            ]
          }
        }
      },
      "Refund": {
        "type": "object",
        "description": "A Refund returns some or all of a succeeded payment to the customer, via whichever provider processed the original.",
        "required": [
          "id",
          "object",
          "amount",
          "currency",
          "payment",
          "status",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the refund. Always prefixed `rf_`.",
            "examples": [
              "rf_3Vp7dK2wQx"
            ]
          },
          "object": {
            "type": "string",
            "const": "refund",
            "description": "String representing the object's type. Always `refund`."
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Refunded amount in minor units.",
            "examples": [
              4900
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "payment": {
            "type": "string",
            "description": "Id of the payment being refunded.",
            "examples": [
              "pay_8Q2mX4nT1cVb"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "requested_by_customer",
              "duplicate",
              "fraudulent",
              "other",
              null
            ],
            "description": "Why the refund was issued. `fraudulent` also feeds the routing engine's risk signals."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed"
            ],
            "description": "Refunds settle asynchronously: `pending` → `succeeded` | `failed`. Subscribe to `refund.succeeded` / `refund.failed` webhooks."
          },
          "provider": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque id of the provider handling the refund — always the one that processed the original payment.",
            "examples": [
              "prov_eu_acq_02"
            ]
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized failure code when `status` is `failed` (e.g. `account_closed`); otherwise `null`."
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "CreateRefundRequest": {
        "type": "object",
        "description": "Payload for creating a refund.",
        "required": [
          "payment"
        ],
        "properties": {
          "payment": {
            "type": "string",
            "description": "Id of the payment to refund. Must be `succeeded`.",
            "examples": [
              "pay_8Q2mX4nT1cVb"
            ]
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Amount to refund, in minor units. Omit to refund the remaining un-refunded balance. Multiple partial refunds are allowed until fully refunded.",
            "examples": [
              4900
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "requested_by_customer",
              "duplicate",
              "fraudulent",
              "other"
            ],
            "description": "Why the refund is issued."
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          }
        }
      },
      "Dispute": {
        "type": "object",
        "description": "A Dispute (chargeback) is a customer formally contesting a payment through their bank or card network. The disputed amount is withheld from your balance while the dispute runs. Respond before `evidence_due_by`: submit evidence to fight it, or accept it. Lifecycle changes emit `dispute.created` / `dispute.updated` / `dispute.closed` events.",
        "required": [
          "id",
          "object",
          "payment",
          "amount",
          "currency",
          "reason",
          "stage",
          "status",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the dispute. Always prefixed `dp_`.",
            "examples": [
              "dp_5Kw2mR8vQz1N"
            ]
          },
          "object": {
            "type": "string",
            "const": "dispute",
            "description": "String representing the object's type. Always `dispute`."
          },
          "payment": {
            "type": "string",
            "description": "Id of the disputed payment (`pay_…`).",
            "examples": [
              "pay_3Vt7Kd9sLm2x"
            ]
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Disputed amount in minor units — may be less than the payment's amount.",
            "examples": [
              12900
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "fraudulent",
              "product_not_received",
              "duplicate",
              "credit_not_processed",
              "general"
            ],
            "description": "Why the customer disputes the payment, normalized across networks:\n\n- `fraudulent` — the cardholder says they didn't authorize it.\n- `product_not_received` — goods or services were not delivered.\n- `duplicate` — charged more than once for the same thing.\n- `credit_not_processed` — a promised refund never arrived.\n- `general` — anything else."
          },
          "stage": {
            "type": "string",
            "enum": [
              "chargeback",
              "pre_arbitration",
              "arbitration"
            ],
            "description": "How far the dispute has escalated: `chargeback` — the initial dispute; `pre_arbitration` — the losing side contested the first outcome; `arbitration` — the card network decides, and its ruling is binding."
          },
          "status": {
            "type": "string",
            "enum": [
              "needs_response",
              "under_review",
              "won",
              "lost",
              "accepted"
            ],
            "description": "Where the dispute stands: `needs_response` — waiting on you, act before `evidence_due_by`; `under_review` — evidence submitted, issuer or network reviewing; `won` — resolved in your favor, withheld funds returned; `lost` — resolved for the cardholder; `accepted` — you accepted liability. `won`, `lost`, and `accepted` are terminal."
          },
          "evidence_due_by": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Deadline to submit evidence or accept, ISO 8601 UTC. Missing it forfeits the dispute (it becomes `lost`). `null` once the dispute is resolved.",
            "examples": [
              "2026-07-30T23:59:59Z"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T18:40:22Z"
            ]
          }
        }
      },
      "SubmitDisputeEvidenceRequest": {
        "type": "object",
        "description": "Payload for submitting dispute evidence.",
        "required": [
          "fields"
        ],
        "properties": {
          "fields": {
            "type": "object",
            "description": "Structured text evidence, keyed by field name. Any keys are accepted; common ones the networks recognize: `product_description`, `customer_communication`, `tracking_number`, `shipping_address`, `refund_policy`, `service_date`.",
            "additionalProperties": {
              "type": "string"
            },
            "examples": [
              {
                "product_description": "Wireless headphones, order ord_9f21_0716",
                "tracking_number": "3SFINS0912837465"
              }
            ]
          },
          "files": {
            "type": "array",
            "description": "Supporting documents (receipts, delivery confirmations, correspondence) as HTTPS URLs reachable by Finscale. May be empty.",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "examples": [
              [
                "https://files.example.com/evidence/ord_9f21_0716-delivery.pdf"
              ]
            ]
          }
        }
      },
      "Customer": {
        "type": "object",
        "description": "A Customer groups payments and saved payment methods under one identity.",
        "required": [
          "id",
          "object",
          "email",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the customer. Always prefixed `cus_`.",
            "examples": [
              "cus_4T8nQb2Wp1Zr"
            ]
          },
          "object": {
            "type": "string",
            "const": "customer",
            "description": "String representing the object's type. Always `customer`."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "The customer's email address. Unique per mode within your account.",
            "examples": [
              "anna@example.com"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full name.",
            "examples": [
              "Anna de Vries"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Phone number in E.164 format."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text description, shown in the dashboard."
          },
          "default_payment_method": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the payment method charged when a payment passes `payment_method_id: \"default\"`."
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "CreateCustomerRequest": {
        "type": "object",
        "description": "Payload for creating a customer.",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "The customer's email address.",
            "examples": [
              "anna@example.com"
            ]
          },
          "name": {
            "type": "string",
            "description": "Full name.",
            "examples": [
              "Anna de Vries"
            ]
          },
          "phone": {
            "type": "string",
            "description": "Phone number in E.164 format."
          },
          "description": {
            "type": "string",
            "description": "Free-text description."
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          }
        }
      },
      "UpdateCustomerRequest": {
        "type": "object",
        "description": "Payload for updating a customer. All fields optional; omitted fields are unchanged.",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "New email address."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "New name, or `null` to clear."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "New phone, or `null` to clear."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "New description, or `null` to clear."
          },
          "default_payment_method": {
            "type": [
              "string",
              "null"
            ],
            "description": "Payment method id to make the default, or `null` to clear. Must be attached to this customer.",
            "examples": [
              "pm_7Wq2xN9dT4Ls"
            ]
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          }
        }
      },
      "Address": {
        "type": "object",
        "description": "A postal address.",
        "properties": {
          "line1": {
            "type": [
              "string",
              "null"
            ],
            "description": "Street address, line 1."
          },
          "line2": {
            "type": [
              "string",
              "null"
            ],
            "description": "Street address, line 2."
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "description": "City or locality."
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Postal or ZIP code."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Two-letter ISO 3166-1 country code.",
            "examples": [
              "NL"
            ]
          }
        }
      },
      "BillingDetails": {
        "type": "object",
        "description": "Billing information attached to a payment method.",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cardholder / account holder name.",
            "examples": [
              "Anna de Vries"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Billing email.",
            "examples": [
              "anna@example.com"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Billing phone, E.164."
          },
          "address": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Address"
              },
              {
                "type": "null"
              }
            ],
            "description": "Billing address, or `null`."
          }
        }
      },
      "PaymentMethod": {
        "type": "object",
        "description": "A reusable payment instrument, attachable to a customer. Sensitive fields are never returned — cards expose brand/last4/expiry only.",
        "required": [
          "id",
          "object",
          "type",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the payment method. Always prefixed `pm_`.",
            "examples": [
              "pm_7Wq2xN9dT4Ls"
            ]
          },
          "object": {
            "type": "string",
            "const": "payment_method",
            "description": "String representing the object's type. Always `payment_method`."
          },
          "type": {
            "$ref": "#/components/schemas/PaymentMethodType"
          },
          "customer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the customer this method is attached to, or `null` when detached.",
            "examples": [
              "cus_4T8nQb2Wp1Zr"
            ]
          },
          "billing_details": {
            "$ref": "#/components/schemas/BillingDetails"
          },
          "card": {
            "type": [
              "object",
              "null"
            ],
            "description": "Card details when `type` is `card`; otherwise `null`.",
            "properties": {
              "brand": {
                "type": "string",
                "description": "Card brand.",
                "examples": [
                  "visa"
                ]
              },
              "last4": {
                "type": "string",
                "description": "Last four digits.",
                "examples": [
                  "4242"
                ]
              },
              "exp_month": {
                "type": "integer",
                "minimum": 1,
                "maximum": 12,
                "description": "Expiry month."
              },
              "exp_year": {
                "type": "integer",
                "description": "Four-digit expiry year.",
                "examples": [
                  2028
                ]
              },
              "funding": {
                "type": "string",
                "enum": [
                  "credit",
                  "debit",
                  "prepaid",
                  "unknown"
                ],
                "description": "Funding type."
              },
              "country": {
                "type": "string",
                "description": "Two-letter issuing country.",
                "examples": [
                  "NL"
                ]
              }
            }
          },
          "sepa_debit": {
            "type": [
              "object",
              "null"
            ],
            "description": "SEPA mandate details when `type` is `sepa_debit`; otherwise `null`.",
            "properties": {
              "iban_last4": {
                "type": "string",
                "description": "Last four characters of the IBAN."
              },
              "mandate_reference": {
                "type": "string",
                "description": "SEPA mandate reference."
              }
            }
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "CreatePaymentMethodRequest": {
        "type": "object",
        "description": "Payload for creating a payment method. Pass **either** a hosted-checkout `token` (live mode) **or** raw details like `card` (test mode only).",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/PaymentMethodType"
          },
          "customer": {
            "type": "string",
            "description": "Customer to attach the method to.",
            "examples": [
              "cus_4T8nQb2Wp1Zr"
            ]
          },
          "token": {
            "type": "string",
            "description": "One-time token from hosted checkout (`tok_…`). The live-mode path — card data never touches your servers."
          },
          "card": {
            "type": "object",
            "description": "Raw card details — accepted in **test mode only**; live-mode requests with raw PANs are rejected with `invalid_request_error`.",
            "required": [
              "number",
              "exp_month",
              "exp_year"
            ],
            "properties": {
              "number": {
                "type": "string",
                "description": "Card number (test cards only).",
                "examples": [
                  "4242424242424242"
                ]
              },
              "exp_month": {
                "type": "integer",
                "minimum": 1,
                "maximum": 12,
                "description": "Expiry month."
              },
              "exp_year": {
                "type": "integer",
                "description": "Four-digit expiry year.",
                "examples": [
                  2028
                ]
              },
              "cvc": {
                "type": "string",
                "description": "Card security code.",
                "examples": [
                  "123"
                ]
              }
            }
          },
          "billing_details": {
            "$ref": "#/components/schemas/BillingDetails"
          },
          "metadata": {
            "type": "object",
            "description": "Set of up to 50 key–value pairs you attach to the object. Keys ≤ 40 chars, values ≤ 500 chars, strings only. Returned unmodified on every read and in webhook payloads.",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 50,
            "examples": [
              {
                "order_id": "ord_9f21_0716"
              }
            ]
          }
        }
      },
      "Merchant": {
        "type": "object",
        "description": "A Merchant is a sub-merchant you onboard for acquiring under your platform. Finscale runs KYB (know-your-business) verification; `capabilities` activate as checks complete, and a `mid` is assigned once the merchant becomes `active`. Status changes emit `merchant.updated` events.",
        "required": [
          "id",
          "object",
          "legal_name",
          "country",
          "mcc",
          "mid",
          "kyb_status",
          "capabilities",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the merchant. Always prefixed `mch_`.",
            "examples": [
              "mch_7Rq3wN8dK2Vs"
            ]
          },
          "object": {
            "type": "string",
            "const": "merchant",
            "description": "String representing the object's type. Always `merchant`."
          },
          "legal_name": {
            "type": "string",
            "description": "Registered legal name of the entity. Fixed after creation.",
            "examples": [
              "Aurora Retail B.V."
            ]
          },
          "trading_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Customer-facing name (doing-business-as). Appears on card statements where the scheme allows.",
            "examples": [
              "Aurora"
            ]
          },
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "Two-letter ISO 3166-1 country code of incorporation. Fixed after creation.",
            "examples": [
              "NL"
            ]
          },
          "mcc": {
            "type": "string",
            "pattern": "^[0-9]{4}$",
            "description": "Four-digit ISO 18245 merchant category code describing the merchant's line of business.",
            "examples": [
              "5734"
            ]
          },
          "mid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Merchant id assigned at the acquiring level once the merchant becomes `active` — this is what appears in scheme clearing records and settlement reports. `null` until then.",
            "examples": [
              "845512000318"
            ]
          },
          "kyb_status": {
            "type": "string",
            "enum": [
              "created",
              "kyb_pending",
              "under_review",
              "active",
              "restricted",
              "suspended"
            ],
            "description": "KYB verification state:\n\n- `created` — record exists, no verification data yet.\n- `kyb_pending` — waiting on required information or documents.\n- `under_review` — checks running.\n- `active` — verified; capabilities can activate and a `mid` is assigned.\n- `restricted` — action required; some capabilities paused.\n- `suspended` — all activity paused."
          },
          "capabilities": {
            "$ref": "#/components/schemas/MerchantCapabilities"
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T08:02:19Z"
            ]
          }
        }
      },
      "MerchantCapabilities": {
        "type": "object",
        "description": "Per-capability activation state. Capabilities move `inactive` → `pending` → `active` as KYB verification completes; a `restricted` or `suspended` merchant can have capabilities paused back to `inactive`.",
        "required": [
          "card_payments",
          "local_methods",
          "payouts"
        ],
        "properties": {
          "card_payments": {
            "type": "string",
            "enum": [
              "inactive",
              "pending",
              "active"
            ],
            "description": "Accepting card payments."
          },
          "local_methods": {
            "type": "string",
            "enum": [
              "inactive",
              "pending",
              "active"
            ],
            "description": "Accepting local payment methods — bank redirects, real-time rails, wallets, vouchers."
          },
          "payouts": {
            "type": "string",
            "enum": [
              "inactive",
              "pending",
              "active"
            ],
            "description": "Receiving payouts to the merchant's settlement bank account."
          }
        }
      },
      "CreateMerchantRequest": {
        "type": "object",
        "description": "Payload for creating a merchant.",
        "required": [
          "legal_name",
          "country",
          "mcc"
        ],
        "properties": {
          "legal_name": {
            "type": "string",
            "description": "Registered legal name of the entity. Cannot be changed later — a different legal entity is a new merchant.",
            "examples": [
              "Aurora Retail B.V."
            ]
          },
          "trading_name": {
            "type": "string",
            "description": "Customer-facing name (doing-business-as).",
            "examples": [
              "Aurora"
            ]
          },
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "Two-letter ISO 3166-1 country code of incorporation. Cannot be changed later.",
            "examples": [
              "NL"
            ]
          },
          "mcc": {
            "type": "string",
            "pattern": "^[0-9]{4}$",
            "description": "Four-digit ISO 18245 merchant category code.",
            "examples": [
              "5734"
            ]
          }
        }
      },
      "UpdateMerchantRequest": {
        "type": "object",
        "description": "Payload for updating a merchant. `legal_name` and `country` are fixed at creation — onboard a new merchant to change the legal entity.",
        "properties": {
          "trading_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Customer-facing name (doing-business-as). Pass `null` to clear it.",
            "examples": [
              "Aurora Home"
            ]
          },
          "mcc": {
            "type": "string",
            "pattern": "^[0-9]{4}$",
            "description": "Four-digit ISO 18245 merchant category code. Changing it can send `kyb_status` back to `under_review`.",
            "examples": [
              "5732"
            ]
          }
        }
      },
      "Payout": {
        "type": "object",
        "description": "A payout of settled funds to your bank account. Created automatically per your payout schedule; read-only via the API.",
        "required": [
          "id",
          "object",
          "amount",
          "currency",
          "status",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the payout. Always prefixed `po_`.",
            "examples": [
              "po_6Fn1mS8vQ2Xc"
            ]
          },
          "object": {
            "type": "string",
            "const": "payout",
            "description": "String representing the object's type. Always `payout`."
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Payout amount in minor units — the net of the linked settlement report.",
            "examples": [
              4900
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_transit",
              "paid",
              "failed"
            ],
            "description": "`pending` → `in_transit` → `paid`. `failed` payouts are retried after you fix the bank details."
          },
          "destination": {
            "type": "object",
            "description": "Redacted pointer to the receiving bank account.",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "iban",
                  "ach",
                  "local"
                ],
                "description": "Account scheme."
              },
              "last4": {
                "type": "string",
                "description": "Last four characters of the account number / IBAN.",
                "examples": [
                  "3401"
                ]
              },
              "country": {
                "type": "string",
                "description": "Two-letter account country.",
                "examples": [
                  "DE"
                ]
              }
            }
          },
          "arrival_date": {
            "type": "string",
            "format": "date",
            "description": "Expected (or actual) date the funds reach your account.",
            "examples": [
              "2026-07-18"
            ]
          },
          "settlement_report": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the settlement report this payout reconciles against.",
            "examples": [
              "stl_2026_07_16_eu01"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "SettlementReport": {
        "type": "object",
        "description": "A per-provider, per-day reconciliation report with normalized totals. The CSV form lists every transaction with your `reference` on each row.",
        "required": [
          "id",
          "object",
          "period_start",
          "period_end",
          "currency",
          "status",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the settlement report. Always prefixed `stl_`.",
            "examples": [
              "stl_2026_07_16_eu01"
            ]
          },
          "object": {
            "type": "string",
            "const": "settlement_report",
            "description": "String representing the object's type. Always `settlement_report`."
          },
          "period_start": {
            "type": "string",
            "format": "date",
            "description": "First settlement day covered (inclusive).",
            "examples": [
              "2026-07-15"
            ]
          },
          "period_end": {
            "type": "string",
            "format": "date",
            "description": "Last settlement day covered (inclusive).",
            "examples": [
              "2026-07-16"
            ]
          },
          "provider": {
            "type": [
              "string",
              "null"
            ],
            "description": "Provider this report covers, or `null` for a consolidated all-provider report.",
            "examples": [
              "prov_eu_acq_01"
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "generating",
              "ready"
            ],
            "description": "`generating` reports have no CSV yet; the `settlement.report.ready` event fires when they flip to `ready`."
          },
          "totals": {
            "type": "object",
            "description": "Normalized totals in minor units. `gross + refunds + fees = net` (refunds and fees are negative).",
            "properties": {
              "gross": {
                "type": "integer",
                "description": "Gross captured volume.",
                "examples": [
                  2041800
                ]
              },
              "refunds": {
                "type": "integer",
                "description": "Refunded volume (negative).",
                "examples": [
                  -96400
                ]
              },
              "fees": {
                "type": "integer",
                "description": "Provider + Finscale fees (negative).",
                "examples": [
                  -31210
                ]
              },
              "net": {
                "type": "integer",
                "description": "Net amount paid out.",
                "examples": [
                  1914190
                ]
              }
            }
          },
          "transaction_count": {
            "type": "integer",
            "description": "Number of transactions (payments + refunds) in the report.",
            "examples": [
              412
            ]
          },
          "payout": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the payout that pays this report's net, once created.",
            "examples": [
              "po_6Fn1mS8vQ2Xc"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "Event": {
        "type": "object",
        "description": "An immutable record of something that happened in your account. Webhook deliveries POST this exact object.",
        "required": [
          "id",
          "object",
          "type",
          "data",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the event. Always prefixed `evt_`.",
            "examples": [
              "evt_5s8Y2kLmN0Ta"
            ]
          },
          "object": {
            "type": "string",
            "const": "event",
            "description": "String representing the object's type. Always `event`."
          },
          "type": {
            "$ref": "#/components/schemas/EventType"
          },
          "data": {
            "type": "object",
            "description": "The event payload.",
            "required": [
              "object"
            ],
            "properties": {
              "object": {
                "type": "object",
                "description": "The API object the event describes — a `payment` for `payment.*` events, a `refund` for `refund.*`, a `dispute` for `dispute.*`, a `merchant` for `merchant.updated`, a `settlement_report` for `settlement.report.ready`, a `provider` for `provider.health.changed`.",
                "additionalProperties": true
              }
            }
          },
          "request_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the API request that caused this event, when there was one (`req_…`); `null` for events Finscale generated internally.",
            "examples": [
              "req_7Hf3kQd2"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "description": "An HTTPS URL that receives signed event deliveries.",
        "required": [
          "id",
          "object",
          "url",
          "enabled_events",
          "status",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the webhook endpoint. Always prefixed `wh_`.",
            "examples": [
              "wh_1KpZ7vRq"
            ]
          },
          "object": {
            "type": "string",
            "const": "webhook_endpoint",
            "description": "String representing the object's type. Always `webhook_endpoint`."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Destination URL. Must be HTTPS with a valid certificate.",
            "examples": [
              "https://example.com/webhooks/finscale"
            ]
          },
          "enabled_events": {
            "type": "array",
            "description": "Event types delivered to this endpoint, or `[\"*\"]` for all.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "payment.succeeded",
                "payment.failed",
                "refund.succeeded"
              ]
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Disabled endpoints receive nothing; missed events remain listable for 30 days."
          },
          "api_version": {
            "type": "string",
            "description": "API version payloads are rendered with.",
            "examples": [
              "v1"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "WebhookEndpointWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "Signing secret (`whsec_…`) used to verify `Finscale-Signature`. **Returned only in this creation response — store it immediately.**",
                "examples": [
                  "whsec_FinscaleDemo000…"
                ]
              }
            }
          }
        ],
        "description": "A webhook endpoint including its one-time-visible signing secret."
      },
      "CreateWebhookEndpointRequest": {
        "type": "object",
        "description": "Payload for creating a webhook endpoint.",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS destination URL.",
            "examples": [
              "https://example.com/webhooks/finscale"
            ]
          },
          "enabled_events": {
            "type": "array",
            "description": "Event types to deliver. Defaults to `[\"*\"]` (all events).",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "payment.succeeded",
                "payment.failed",
                "refund.succeeded"
              ]
            ]
          }
        }
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "description": "Payload for updating a webhook endpoint. All fields optional.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "New HTTPS destination URL."
          },
          "enabled_events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "New event-type subscription list, or `[\"*\"]`."
          },
          "status": {
            "type": "string",
            "enum": [
              "enabled",
              "disabled"
            ],
            "description": "Pause (`disabled`) or resume (`enabled`) deliveries."
          }
        }
      },
      "RoutingRuleMatch": {
        "type": "object",
        "description": "Conditions a transaction must meet for the rule to apply. Omitted (or `null`) conditions match everything; multiple conditions AND together.",
        "properties": {
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Z]{3}$",
            "description": "Match this ISO 4217 currency.",
            "examples": [
              "EUR"
            ]
          },
          "method": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PaymentMethodType"
              },
              {
                "type": "null"
              }
            ],
            "description": "Match this payment method type."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Match the customer's two-letter ISO 3166-1 country.",
            "examples": [
              "NL"
            ]
          },
          "amount_gte": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Match amounts greater than or equal to this, in minor units.",
            "examples": [
              100000
            ]
          }
        }
      },
      "RoutingActionPreferProvider": {
        "type": "object",
        "description": "Try the named provider first. Failover still applies if it declines or times out.",
        "required": [
          "type",
          "provider"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "prefer_provider"
          },
          "provider": {
            "type": "string",
            "description": "Opaque provider id to prefer.",
            "examples": [
              "prov_eu_acq_02"
            ]
          }
        }
      },
      "RoutingActionWeightSplit": {
        "type": "object",
        "description": "Distribute matching volume across providers by weight. Weights must sum to 100.",
        "required": [
          "type",
          "weights"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "weight_split"
          },
          "weights": {
            "type": "array",
            "minItems": 2,
            "description": "Providers and their share of matching volume.",
            "items": {
              "type": "object",
              "required": [
                "provider",
                "weight"
              ],
              "properties": {
                "provider": {
                  "type": "string",
                  "description": "Opaque provider id.",
                  "examples": [
                    "prov_eu_acq_01"
                  ]
                },
                "weight": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 99,
                  "description": "Share in percent. All weights sum to 100.",
                  "examples": [
                    70
                  ]
                }
              }
            }
          }
        }
      },
      "RoutingActionBlock": {
        "type": "object",
        "description": "Reject matching transactions before any provider is attempted. The payment fails immediately with code `blocked_by_routing_rule`.",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "block"
          }
        }
      },
      "RoutingRuleAction": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/RoutingActionPreferProvider"
          },
          {
            "$ref": "#/components/schemas/RoutingActionWeightSplit"
          },
          {
            "$ref": "#/components/schemas/RoutingActionBlock"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "prefer_provider": "#/components/schemas/RoutingActionPreferProvider",
            "weight_split": "#/components/schemas/RoutingActionWeightSplit",
            "block": "#/components/schemas/RoutingActionBlock"
          }
        },
        "description": "What happens when the rule matches: prefer one provider, split by weight, or block."
      },
      "RoutingRule": {
        "type": "object",
        "description": "A per-merchant routing rule. Active rules are evaluated by ascending `priority`; the first match wins. No match → smart routing.",
        "required": [
          "id",
          "object",
          "priority",
          "active",
          "match",
          "action",
          "livemode",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the routing rule. Always prefixed `rr_`.",
            "examples": [
              "rr_2Nc6wB4hJ9Ke"
            ]
          },
          "object": {
            "type": "string",
            "const": "routing_rule",
            "description": "String representing the object's type. Always `routing_rule`."
          },
          "priority": {
            "type": "integer",
            "minimum": 1,
            "description": "Evaluation order — lowest number first. Must be unique among your rules.",
            "examples": [
              10
            ]
          },
          "active": {
            "type": "boolean",
            "description": "Inactive rules are skipped during evaluation."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable label shown in the dashboard.",
            "examples": [
              "Prefer prov_eu_acq_02 for iDEAL in the Netherlands"
            ]
          },
          "match": {
            "$ref": "#/components/schemas/RoutingRuleMatch"
          },
          "action": {
            "$ref": "#/components/schemas/RoutingRuleAction"
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Time the object was created, ISO 8601 UTC.",
            "examples": [
              "2026-07-16T09:24:31Z"
            ]
          }
        }
      },
      "CreateRoutingRuleRequest": {
        "type": "object",
        "description": "Payload for creating a routing rule.",
        "required": [
          "priority",
          "action"
        ],
        "properties": {
          "priority": {
            "type": "integer",
            "minimum": 1,
            "description": "Evaluation order — lowest number first. Must be unique among your rules.",
            "examples": [
              10
            ]
          },
          "active": {
            "type": "boolean",
            "default": true,
            "description": "Create the rule switched on (default) or off."
          },
          "description": {
            "type": "string",
            "description": "Human-readable label.",
            "examples": [
              "Prefer prov_eu_acq_02 for iDEAL in the Netherlands"
            ]
          },
          "match": {
            "$ref": "#/components/schemas/RoutingRuleMatch"
          },
          "action": {
            "$ref": "#/components/schemas/RoutingRuleAction"
          }
        }
      },
      "UpdateRoutingRuleRequest": {
        "type": "object",
        "description": "Payload for updating a routing rule. All fields optional; omitted fields are unchanged.",
        "properties": {
          "priority": {
            "type": "integer",
            "minimum": 1,
            "description": "New evaluation priority."
          },
          "active": {
            "type": "boolean",
            "description": "Switch the rule on or off."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "New label, or `null` to clear."
          },
          "match": {
            "$ref": "#/components/schemas/RoutingRuleMatch"
          },
          "action": {
            "$ref": "#/components/schemas/RoutingRuleAction"
          }
        }
      },
      "Provider": {
        "type": "object",
        "description": "One of the acquirers/PSPs behind Finscale, exposed as an opaque id. Read-only: Finscale manages provider contracts, credentials, and health.",
        "required": [
          "id",
          "object",
          "methods",
          "regions",
          "status",
          "auth_rate_7d"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the provider. Always prefixed `prov_`.",
            "examples": [
              "prov_eu_acq_01"
            ]
          },
          "object": {
            "type": "string",
            "const": "provider",
            "description": "String representing the object's type. Always `provider`."
          },
          "methods": {
            "type": "array",
            "description": "Payment method types this provider can process.",
            "items": {
              "$ref": "#/components/schemas/PaymentMethodType"
            }
          },
          "regions": {
            "type": "array",
            "description": "Regions the provider serves (e.g. `EU`, `UK`, `US`, `BR`, `KE`, `SEA`).",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "EU",
                "UK"
              ]
            ]
          },
          "currencies": {
            "type": "array",
            "description": "Settlement currencies the provider supports.",
            "items": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            },
            "examples": [
              [
                "EUR",
                "GBP"
              ]
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "degraded",
              "disabled"
            ],
            "description": "Provider health. `degraded` providers are down-weighted by smart routing; `disabled` providers receive no traffic."
          },
          "auth_rate_7d": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Platform-wide authorization rate over the last 7 days, 0–1. One input to smart routing's scoring.",
            "examples": [
              0.947
            ]
          }
        }
      },
      "BalanceAmount": {
        "type": "object",
        "description": "An amount in one currency.",
        "required": [
          "amount",
          "currency"
        ],
        "properties": {
          "amount": {
            "type": "integer",
            "description": "Amount in minor units.",
            "examples": [
              1914190
            ]
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter ISO 4217 currency code, uppercase.",
            "examples": [
              "EUR"
            ]
          }
        }
      },
      "Balance": {
        "type": "object",
        "description": "Your balance across all providers, netted per currency.",
        "required": [
          "object",
          "available",
          "pending",
          "livemode"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "balance",
            "description": "String representing the object's type. Always `balance`."
          },
          "available": {
            "type": "array",
            "description": "Settled funds ready for payout, per currency.",
            "items": {
              "$ref": "#/components/schemas/BalanceAmount"
            }
          },
          "pending": {
            "type": "array",
            "description": "Captured funds awaiting provider settlement, per currency.",
            "items": {
              "$ref": "#/components/schemas/BalanceAmount"
            }
          },
          "livemode": {
            "type": "boolean",
            "description": "`true` for objects created with a live-mode key (`sk_live_••••••••••••`), `false` in test mode."
          }
        }
      },
      "Deleted": {
        "type": "object",
        "description": "Confirmation envelope returned by DELETE endpoints.",
        "required": [
          "id",
          "object",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Id of the deleted object.",
            "examples": [
              "cus_4T8nQb2Wp1Zr"
            ]
          },
          "object": {
            "type": "string",
            "description": "Type of the deleted object.",
            "examples": [
              "customer"
            ]
          },
          "deleted": {
            "type": "boolean",
            "const": true,
            "description": "Always `true`."
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Machine-readable error detail. `type` tells you how to react; `code` tells you exactly what happened.",
        "required": [
          "type",
          "message",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invalid_request_error",
              "authentication_error",
              "card_error",
              "idempotency_error",
              "rate_limit_error",
              "api_error"
            ],
            "description": "Error class, aligned with the HTTP status: `invalid_request_error` (400/404), `authentication_error` (401), `card_error` (402), `idempotency_error` (409), `rate_limit_error` (429), `api_error` (5xx)."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Specific error code, e.g. `card_declined`, `resource_missing`, `idempotency_key_reused`.",
            "examples": [
              "card_declined"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation. Safe to log; do not show verbatim to customers.",
            "examples": [
              "The card was declined by the issuer."
            ]
          },
          "param": {
            "type": [
              "string",
              "null"
            ],
            "description": "The request parameter the error relates to, when applicable.",
            "examples": [
              "amount"
            ]
          },
          "doc_url": {
            "type": "string",
            "format": "uri",
            "description": "Link to the relevant docs page.",
            "examples": [
              "https://docs.finscale.dev/errors/#card_declined"
            ]
          },
          "request_id": {
            "type": "string",
            "description": "Id of this API request (`req_…`). Include it when contacting support.",
            "examples": [
              "req_7Hf3kQd2"
            ]
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "description": "Every non-2xx response uses this envelope.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/Error"
          }
        }
      },
      "PaymentList": {
        "type": "object",
        "description": "A paginated list of payments. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of payments, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Payment"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/payments"
            ]
          }
        }
      },
      "RefundList": {
        "type": "object",
        "description": "A paginated list of refunds. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of refunds, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Refund"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/refunds"
            ]
          }
        }
      },
      "DisputeList": {
        "type": "object",
        "description": "A paginated list of disputes. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of disputes, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Dispute"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/disputes"
            ]
          }
        }
      },
      "CustomerList": {
        "type": "object",
        "description": "A paginated list of customers. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of customers, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Customer"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/customers"
            ]
          }
        }
      },
      "PaymentMethodList": {
        "type": "object",
        "description": "A paginated list of payment methods. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of payment methods, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/PaymentMethod"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/payment_methods"
            ]
          }
        }
      },
      "MerchantList": {
        "type": "object",
        "description": "A paginated list of merchants. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of merchants, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Merchant"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/merchants"
            ]
          }
        }
      },
      "PayoutList": {
        "type": "object",
        "description": "A paginated list of payouts. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of payouts, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Payout"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/payouts"
            ]
          }
        }
      },
      "SettlementReportList": {
        "type": "object",
        "description": "A paginated list of settlement reports. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of settlement reports, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/SettlementReport"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/settlement_reports"
            ]
          }
        }
      },
      "EventList": {
        "type": "object",
        "description": "A paginated list of events. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of events, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/events"
            ]
          }
        }
      },
      "WebhookEndpointList": {
        "type": "object",
        "description": "A paginated list of webhook endpoints. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of webhook endpoints, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/webhook_endpoints"
            ]
          }
        }
      },
      "RoutingRuleList": {
        "type": "object",
        "description": "A paginated list of routing rules. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of routing rules, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/RoutingRule"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/routing_rules"
            ]
          }
        }
      },
      "ProviderList": {
        "type": "object",
        "description": "A paginated list of providers. Iterate with `starting_after` while `has_more` is `true`.",
        "required": [
          "object",
          "data",
          "has_more",
          "url"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "String representing the object's type. Always `list`."
          },
          "data": {
            "type": "array",
            "description": "Page of providers, most recently created first.",
            "items": {
              "$ref": "#/components/schemas/Provider"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more items exist beyond this page."
          },
          "url": {
            "type": "string",
            "description": "The endpoint that produced this list.",
            "examples": [
              "/v1/providers"
            ]
          }
        }
      }
    }
  }
}
